DEV Community

Cover image for Combine many ngrx selectors with combineLatest in Angular
Nick Raphael
Nick Raphael

Posted on • Updated on

Combine many ngrx selectors with combineLatest in Angular

Let us suppose we have an area of store that hold the status of a save operation. Our status can have the values InProgress, Completed and Failed.

We have two selectors already defined...

export const getOperationFailed = createSelector(
  getOperationState,
  state => state.status === 'Failed'
);

export const getOperationCompleted = createSelector(
  getOperationState,
  state => state.status === 'Completed'
);
Enter fullscreen mode Exit fullscreen mode

Now suppose we have a stop button on our angular template that should be disabled if the status is either Completed or Failed. It would be pretty simple to do the following in our component...

this.getRunProgressCompleted$ = this.store.select(getRunProgressCompleted);
this.getRunProgressFailed$ = this.store.select(getRunProgressFailed);

<button
      (click)="stop()"
      [disabled]="(getOperationCompleted$ | async) || (getOperationFailed$ | async)"
>Stop</button>
Enter fullscreen mode Exit fullscreen mode

Instead, we can use the power of the rxjs combineLatest operator to combine our selectors.

combineLatest marble diagram

There are two key facts about combineLatest...
1. When any observable emits a value, emit the last emitted value from each.
2. combineLatest will not emit an initial value until each observable emits at least one value.

So we can create a single observable that resolves as true if the operation either completed or failed:

this.getOperationCompletedOrFailed$ = combineLatest(
  this.store.select(getOperationCompleted),
  this.store.select(getOperationFailed),
  (failed, completed) => failed || completed
);
Enter fullscreen mode Exit fullscreen mode

And bind our button like this:

<button
  (click)="stop()"
  [disabled]="getOperationCompletedOrFailed$ | async"
>Stop</button>
Enter fullscreen mode Exit fullscreen mode

It's good practice to minimise the number of local variables on your components. CombineLatest is one of those little tools that helps.

Top comments (0)