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'
);
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>
Instead, we can use the power of the rxjs combineLatest operator to combine our selectors.
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
);
And bind our button like this:
<button
(click)="stop()"
[disabled]="getOperationCompletedOrFailed$ | async"
>Stop</button>
It's good practice to minimise the number of local variables on your components. CombineLatest is one of those little tools that helps.