Utilize toggle functionality for page rotation with rxjs in Angular framework

Managing a project that involves a container holding multiple cards across different pages can be overwhelming. To address this, the screen automatically rotates to the next page after a set time interval or when the user presses the space bar.

To enhance the functionality, we have introduced a toggle button to disable the automatic rotation. I have integrated an 'EventEmitter' for the toggle button in the 'toggleEmitter' function below, but as I am fairly new to rxjs, I am unsure how to utilize it effectively to halt the rotation process. Can anyone offer guidance on this matter?

@Component({
  selector: 'rotator-container',
  templateUrl: './rotator-container.component.html',
})
export class RotatorContainerComponent implements AfterViewInit, OnDestroy {
  @ContentChildren(RotatorItemComponent, { read: ElementRef })
  rotatorItems: QueryList<ElementRef>;

  @Input() rotationInterval = 30 * 1000;

  @Output() toggleEmitter: EventEmitter<MatSlideToggleChange> =
    new EventEmitter();
  toggle(event: MatSlideToggleChange) {
    this.toggleEmitter.emit(event);
  }

  timer$ = this.activatedRoute.queryParams.pipe(
    map(params => params['rotate']),
    switchMap(rotate =>
      rotate === 'false' ? of(0) : timer(0, this.rotationInterval)
    )
  );

  spaceCounter$ = fromEvent<KeyboardEvent>(document, 'keydown').pipe(
    filter(({ code }) => code === 'Space'),
    tap(e => e.preventDefault()),
    map(() => 1),
    scan((acc, curr) => acc + curr, 0),
    startWith(0)
  );

  rotationCounter$ = combineLatest([this.timer$, this.spaceCounter$]).pipe(
    map(([index, offset]) => index + offset)
  );

  rotatorSubscription: Subscription;

  constructor(private activatedRoute: ActivatedRoute) {}

  ngAfterViewInit() {
    const rotatorItemsLength$ = this.rotatorItems.changes.pipe(
      map(() => this.rotatorItems.length),
      startWith(this.rotatorItems.length)
    );

    const visibleIndex$ = combineLatest([
      this.rotationCounter$,
      rotatorItemsLength$,
    ]).pipe(
      map(([index, length]) => index % length),
      startWith(0)
    );

    this.rotatorSubscription = visibleIndex$.subscribe(visibleIndex =>
      this.rotatorItems.forEach((item, index) => {
        (<HTMLElement>item.nativeElement).style.visibility =
          visibleIndex === index ? 'visible' : 'hidden';
        (<HTMLElement>item.nativeElement).style.position =
          visibleIndex === index ? 'relative' : 'absolute';
      })
    );
  }

  ngOnDestroy() {
    this.rotatorSubscription && this.rotatorSubscription.unsubscribe();
  }
}

Answer №1

It seems like using an EventEmitter is not necessary in this case. Instead, consider adjusting the functionality of the timer$ Observable.

One possible approach to try is as follows:

To start, create a Subject that will emit either true or

false> whenever the state of the toggle button changes. Specifically, it emits <code>true
if the button is toggled on and false otherwise.

This code snippet demonstrates how to achieve this:

// Use a BehaviorSubject to initiate with a specific value, such as false
toggleSubject = new BehaviourSubject<bool>(false)
....
toggle(event: MatSlideToggleChange) {
    this.toggleSubject.next(event.checked);
}

Next, modify the timer$ Observable. Here's one potential way to go about it:

// Initially, rename the current timer$ to _timer$
_timer$ = this.activatedRoute.queryParams.pipe(
  map(params => params['rotate']),
  switchMap(rotate =>
    rotate === 'false' ? of(0) : timer(0, this.rotationInterval)
  )
);

// Then redefine the timer$ stream based on toggleSubject
timer$ = toggleSubject.pipe(
  // Switch to a new stream whenever toggleSubject emits
  switchMap(toggleVal => {
    // If the toggleButton is on, automatic rotation is off; otherwise, it's on
    // This is achieved by returning an Observable that emits 0 if the button is on,
    // or the original definition of timer$ if it's off
    return toggleVal ? of(0) : this._timer$
    
  })
)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

In situations where there may be a duplicate, what alternative can I utilize in place of the id attribute?

I understand that almost any element in the DOM can have an "id" attribute, and I've used it to track each client in a table of clients. Although ids should not be repeated, my rows are assigned unique identifiers based on each person's "clientId ...

jQuery does not trigger the error event for a 403 status code when loading a new image src

Currently working on a project that involves implementing a static Google map on a webpage. The challenge I am facing is resizing the map dynamically when the page size changes. In order to achieve this, I have created a function that triggers on page resi ...

Nested Ajax request fails and triggers a full page reload

My goal is to search for product information and images using a product code input on index.php. The query runs in open_first.php via an ajax post request, which works perfectly. open_first.php displays images that can be selected by clicking on them. How ...

Multiple Invocations of Angular NgrxStore Action Dispatched within Selector Function

Currently, I am working on an Angular project utilizing ngRx store for the first time. In this project, I need to dispatch an action to fetch users' courses after retrieving the user from the Store. However, I have encountered a problem where the acti ...

The asynchronous ajax request is leading to a browser freeze

In the HTML page, I have two sets of a and p elements that are initially set to display:none. At the bottom of the page, there is a function being called with their respective ID's and values, which will enable one of them based on certain conditions ...

What is the process of transforming a jQuery load method into native JavaScript, without using any additional libraries?

Recently, I successfully implemented this ajax functionality using jQuery: $(function(){ $('#post-list a').click(function(e){ var url = $(this).attr('href'); $('#ajax-div').load(url+ " #post"); e.preventDefaul ...

What is the best way to programmatically insert new rows into a table

I am currently working with the foundation 5 framework (not sure if this is relevant). I need to ensure that each CELL is treated as a distinct item/value when passing information to another page, and I am unsure of how to approach this issue. It should cr ...

Vue.js - The error message "$slots have 'el' is null" indicates a problem with the element in

When trying to access the Vuejs $slots instance, I encounter el = null, but type = "div" Here is the template: <slot name="head"> <h1> {{ text }} </h1> </slot> And in the script section: ... ...

Vue.js Element UI dialog box

Is there a method to customize the close button in el-dialog and replace it with my own design? For instance, can I change the default close button located at the top left corner of the dialog? <el-dialog title="Tips" :visible.sync=" ...

Tips on crafting tailored CSS styling for targeted div elements such as before and after:

Looking to style specific div elements with the same class name? <div class="main"> <div class="banner_image"> banner 1</div> <div class="banner_image ">banner 2</div> <div class="banner_image ">banner 3</di ...

Include a character in a tube using Angular

Hey everyone, I have a pipe that currently returns each word with the first letter uppercase and the rest lowercase. It also removes any non-English characters from the value. I'm trying to figure out how to add the ':' character so it will ...

Why is it necessary to create a new object in Node.js to establish a server?

After reviewing the information about socket.io, there is one aspect that I find confusing. I understand that to create a server, it can be done like this: var io = require ("socket.io")(); However, I am curious about why it necessitates creating a new ...

Attempting to incorporate an npm package (specifically Howler) into an Angular 2 application

I'm facing an issue with importing Howler into my Angular 2 app as it doesn't have a typings file. Despite my efforts in searching for a solution, I haven't been able to find anything helpful. Can someone guide me on how to import "howler" i ...

Designing a versatile Angular component for inputting data (Mailing Address)

Currently, I am in the process of developing an Angular 11 application that requires input for three distinct mailing addresses. Initially, I thought I had a clear understanding of what needed to be done, only to encounter warnings about elements with non- ...

Waiting for nested observables to complete in Angular 2

Before proceeding to another page in my Angular app, I need two nested Observables to complete. However, I am facing synchronization issues as they are nested within each other. These Observables are initialized in my authentication service. authentication ...

Retrieving a value from an array at random to assign to a different variable

I have different options for a specific variable depending on the scenario --> var lowSpeed = Math.random() * (45 - 30) + 30; var mediumSpeed = Math.random() * (60 - 45) + 45; var highSpeed = Math.random() * (80 - 60) + 45; var highwaySpeed = Math.rando ...

Struggling with a 400 Bad Request Error in Angular with WebAPI Integration

I've been working on creating a database to keep track of comics, and so far I can successfully add new comics and retrieve them using GET requests. However, I've hit a roadblock when trying to update existing comics using PUT requests. Every tim ...

Implementing a Div response within the actionPerformed method

I've spent hours working on this javascript/ajax code trying to get it to add a div response that was echoed by a php script. Any assistance with this would be greatly appreciated. <form id="form1" name="form1" method="post" enctype="multipart/for ...

How can I store unique and only selected checkbox values in an array using Angular?

I need assistance with creating an array from three checkboxes. The array should only contain the values of the checked checkboxes and should not include duplicates. I have attempted to achieve this functionality, but the values are still being added rega ...

Using html data attributes to encode JSON data with strings

Looking for a way to pass data to JavaScript, I decided to create a template tag as shown below: from django.utils.safestring import mark_safe from django import template import json register = template.Library() @register.simple_tag def mydata(): r ...