ViqMontana
ViqMontana

Reputation: 5688

Rxjs - condition pipeable operator

I'm using Angular and Ngrx. I'm retrieving lots of data from my backend in many seperate calls; 2 pieces of the data in my Ngrx store state are dashboardState.issuesState.issues and dashboardState.defaultAssetId.

I have the following code to call the 'setCurrentlySelectedAsset' method:

this.store.pipe(
      select((state: AppState) => state.dashboard.defaultAssetId),
      tap((selectedAssetId: number) => this.setCurrentlySelectedAsset(selectedAssetId))
    ).subscribe();

This works, and the setCurrentlySelectedAsset method is called every time state.dashboard.defaultAssetId emits a value, great.

But I only want this method to be called IF dashboardState.issuesState.issues has a value (i.e. the backend request has been completed).

A possible solution could be this:

this.store.pipe(
      select((state: AppState) => state.dashboard),
      tap((dashboardState: State) =>
      {
        if (dashboardState.issuesState.issues && dashboardState.defaultAssetId)
        {
          this.setCurrentlySelectedAsset(dashboardState.defaultAssetId)
        }
      })
    ).subscribe();

But now my tap will be called every time anything on dashboardState changes (and a lot will changes on there).

Any ideas? I've looked but haven't been able to find a pipeable operator to put inbetween the select and tap, which will then only proceed to tap if a certain condition, i.e. dashboardState.issuesState.issues having a value, is met.

Upvotes: 2

Views: 798

Answers (2)

Tim Klein
Tim Klein

Reputation: 2758

Here is a solution that utilizes the filter operator:

this.store.pipe(
  select((state: AppState) => state.dashboard),
  filter((dashboardState: State) => dashboardState.issuesState.issues && dashboardState.defaultAssetId),
  tap((dashboardState: State) => this.setCurrentlySelectedAsset(dashboardState.defaultAssetId))
).subscribe();

If the predicate returns true, then the value will be emitted to tap, otherwise, it will not be emitted.

Upvotes: 2

thomi
thomi

Reputation: 1687

Have a look at filter. You can pipe it between your select and tap and emits only if your condition is met.

Here is the description from the above link.

Filter items emitted by the source Observable by only emitting those that satisfy a specified predicate.

So you could go for something like:

this.store.pipe(
      select((state: AppState) => state.dashboard),
      filter(dashboardState => dashboardState.issuesState.issues && dashboardState.defaultAssetId),
      tap(dashboardState => this.setCurrentlySelectedAsset(dashboardState.defaultAssetId))
    ).subscribe();

Upvotes: 1

Related Questions