angularngrxngrx-router-store

Action with parameter or parameter from router-store


Problem:

I have component and url such as:

https://127.0.0.0/car/carName1/view1

and

ngOnInit(): void {
    this.store$.dispatch(Actions.loadView());    
  }

This dispatch action, and effect gets single view from the service and add it to collection

state will look like this:

{
  views: {

     view1: {
        data: []
     }

     view2: {
        data: []
     }
  }
}

Now, inside same component I need to fetch more from view which contains more data I need, or in other words I need to select some that from it

    ngOnInit(): void {
        this.data$ = this.store$.select(Selectors.selectMoreData);
        this.store$.dispatch(Actions.loadView());    
      }

Problem is that Selectors.selectMoreData needs view name/key. Because state has more views than just one single for current component.

What possibilities I have? Like in effects use router-store and get key from url? Or should I step back because this is totally wrong.


Solution

  • UPDATED

    After discussion in comments my answer would be the next one: do everything in ngOnInit to avoid complexity of passing variables here and there.

    ngOnInit(): void {
      this.data$ = this.store$.select(Selectors.selectMoreData, this.viewName);
      this.store$.dispatch(Actions.loadView());    
    }
    

    or in case of router-store

    ngOnInit(): void {
      this.data$ = this.store$.pipe(
        select(selectRouteParam('viewName')),
        switchMap(viewName => combineLatest([
          of(viewName),
          this.store$.select(Selectors.selectMoreData, this.viewName)),
        ]),
        map(([viewName, data]) => ({viewName, data}));
      );
    
      this.store$.dispatch(Actions.loadView());    
    }
    

    and in template

    <ng-container *ngIf="data$ | async as data">
      <child [view]="data.viewName" [data]="data.data"></child>
    </ng-container>
    

    or in case of this.activatedRoute

    ngOnInit(): void {
      this.data$ = this.activatedRoute.paramMap.pipe(
        map(params => params.get('viewName')),
        switchMap(viewName => combineLatest([
          of(viewName),
          this.store$.select(Selectors.selectMoreData, this.viewName)),
        ]),
        map(([viewName, data]) => ({viewName, data}));
      );
    
      this.store$.dispatch(Actions.loadView());    
    }
    

    ORIGINAL

    You miss the 3rd option - to use a resolver that would provider data for your component in ActivatedRoute.data, you can find an example in the answer here: https://stackoverflow.com/a/61836566/13112018.


    Besides that back to viewName. You can add it as route's data and then it will be accessible in the router-store too.

    For example you can define a route like that.

    {
        path: 'test',
        component: TestComponent,
        data: {
            viewName: 'test',
        },
    },
    

    and then to use router-store to select it

    this.store.select(selectRouteData).subscribe(console.log); // {viewName: 'test'}