Search code examples
angularrxjsngrxngrx-entity

Display single ngrx entity within ngFor loop using Ids


I'm using ng6 with NGRX to display two datasets in the view. The first dataset is the complete dataset. The second dataset is an subset of the first dataset.

I need to use an ngFor loop on the second dataset, which provides an id, and within the loop use the id to display a single entity from the first dataset.

component.ts

export class ViewComponent implements OnInit {
  datasetOne$: Observable<data[]>;
  datasetTwo$: Observable<data[]>;

  constructor(private store: Store<fromStore.DatasetState>) {}

  ngOnInit() {
    this.store.dispatch(new fromStore.LoadDatasetOne());
    this.store.dispatch(new fromStore.LoadDatasetTwo());
    this.datasetOne$ = this.store.select(fromStore.getDatasetOne);
    this.datasetTwo$ = this.store.select(fromStore.getDatasetTwo);
  }

}

component.html

<ul>
    <li *ngFor="let data of (datasetOne$ | async)">{{ data.name }}</li>  
</ul>

Subset:

<ul>
    <li *ngFor="let subData of (datasetTwo$ | async)">{{ subData.id }}</li>  
</ul>

The view displays both subset correctly this far, names and ids (numbers)

The subData.id corresponds to a name in datasetOne, I want to display the name instead of the id

Is it something like this for the view:

<li *ngFor="let subData of (datasetTwo$ | async)">{{ getNameById(subData.id) }}</li>

but I have not been successful in writing a method that can grab a single entity from datasetOne$


Solution

  • Since you're already using selectors I would suggest to create a new selector based on the current two.

    const combinedSelector = createSelect(datasetOne, datasetTwo,
      (one, two) => ...
    )
    

    If this isn't possible, you could also the following, as mentioned in NgRx: Parameterized selectors

    export const selectCustomer = createSelector(
      selectCustomers, 
      customers => (id: string) => customers[id]
    );
    
    // tip: it’s also possible to memoize the function if needed
    export const selectCustomer = createSelector(
      selectCustomers, 
      customers => memoize((id: string) => customers[id])
    );
    
    // and in the HTML
    {{ (customers | async)(id).name }}