Action with parameter or parameter from router-store

718 Views Asked by At

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.

1

There are 1 best solutions below

11
On BEST ANSWER

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'}