Search code examples
angularsignalsangular-signals

Assigning an Observable based on the value of a signal


In my app, I declare a movies list based on the menu item selected (top movies, upcoming movies...). I was doing that with a BehaviorSubject in a service with the following code:

in my component:

readonly movies$: Observable<Movie[]> = this.storeService.menuItemSelected$.pipe(
  switchMap(menuItem => {
    return menuItem === 'watchlist' ? this.movieService.getWatchlistMovies() 
      : this.movieService.getMoviesByCategory(menuItem);
  })
);

in my service:

private readonly menuItemSelectedSource = new BehaviorSubject<Category>('now_playing');
readonly menuItemSelected$ = this.menuItemSelectedSource.asObservable();

updateMenuSelection(menuItem: Category): void {
  this.menuItemSelectedSource.next(menuItem);
}

Now I'm trying to do the same but using a signal for menuItemSelected instead of a BehaviorSubject.

I made the following changes:

menuItemSelected = signal<Category>('now_playing');

updateMenuSelection(menuItem: Category): void {
  this.menuItemSelected.set(menuItem);
}

My question is, how do I declare my movies$ Observable based on that menuItemSelected signal ?

readonly movies$: Observable<Movie[]> = ... ?


Solution

  • Convert the signal to an observable using toObservable from '@angular/core/rxjs-interop', then substitute it with the behaviour subject

    import { toObservable } from '@angular/core/rxjs-interop';
    import { signal } from '@angular/core';
    ...
    
    ...
    menuItemSelected = signal<Category>('now_playing');
    
    updateMenuSelection(menuItem: Category): void {
        this.menuItemSelected.set(menuItem);
    }
    
    readonly movies$: Observable<Movie[]> = toObservable(this.storeService.menuItemSelected).pipe(
          switchMap(menuItem => {
              return menuItem === 'watchlist' ? this.movieService.getWatchlistMovies() 
                : this.movieService.getMoviesByCategory(menuItem);
          })
    );
    ...