Search code examples
angularreduxrxjsngrx

NgRx dynamic switch case behavior parametrized selector


I have a component where I get multiple data from different NgRx feature states. I'm not that fluent in RxJS and I struggle with the sequencing of the data flow.

The code below is run at component initialization :

// UI related display context
this.displayContextId$ = this.store.select(selectCurrentDisplayContextId);
this.displayContextId$.subscribe();

// Data related to this component's parent
this.currentItem$ = this.store.select(selectCurrentItem);

// Some data from the state
this.featureAData$ = this.store.select(featureADataByItemId(this.subItem.id));
this.featureBData$ = this.store.select(selectfeatureBDataByItemId(this.subItem.id));

this.featureBData$.subscribe();

// Some data that needs featureAData to be fetched
this.featureCData$ = this.featureAData$.pipe(
    mergeMap(featureA => this.store.select(selectSomeDataById(featureA.someId)))
);

this.featureCData$.subscribe();

The pseudo code describes the essence of what I try to achieve and currently doesn't work :

// When displayContextId changes, select one specific item from the store which is identified by an id issued of the concatenation of other ids (from the data model specs)

this.displayContextId$.pipe(
).subscribe(displayContextId => {
    switch (displayContextId) {
        case DisplayContexts.TypeA:
            this.displayContextItem$ = this.featureAData$.pipe(
                mergeMap(featureA => this.store.select(selectDisplayContextItemById(displayContextId + '-' + featureA.someId)))
            );
            break;
        case DisplayContexts.TypeB:
            console.log(d);
            this.displayContextItem$ = this.featureCData$.pipe(
                mergeMap(featureC => this.store.select(selectDisplayContextItemItemById(displayContextId + '-' + featureC.someId)))
            );
            break;
    }
});

this.displayContextItem$.subscribe();

I'm perfectly aware that it's not the RxJS manner of doing this. My goal is to dynamically reselect data from the store based on different input sources which are evolving during the component lifecycle.

Also, I don't know where to put this in the component lifecycle.

What could be a working implementation of this ?

Many thanks,


Solution

  • Try doing something like this:

    import { switchMap } from 'rxjs/operators
    ....
    this.displayContextItem$ = this.displayContextId$.pipe(
      // take the value of displayContextId and switch to a new observable depending on its value
      switchMap(displayContextId => {
        switch (displayContextId) {
            case DisplayContexts.TypeA:
                return this.featureAData$.pipe(
                    mergeMap(featureA => this.store.select(selectDisplayContextItemById(displayContextId + '-' + featureA.someId)))
                );
            case DisplayContexts.TypeB:
                console.log(d);
                return this.featureCData$.pipe(
                    mergeMap(featureC => this.store.select(selectDisplayContextItemItemById(displayContextId + '-' + featureC.someId)))
                );
        }
      }),
    );
    // after you initialized it, you can subscribe to it
    this.displayContextItem$.subscribe();