0

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$

2 Answers2

1

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 }}
timdeschryver
  • 14,415
  • 1
  • 19
  • 32
  • A combined selector was the preferred method. First argument is an array of entities, second argument an array of `id`s then map over `two` and return the `entity[id]` – myLogicIsWrong Sep 10 '18 at 16:04
0

You basically have two streams and you want to create a new stream using values from both. You need to use zip

Doc : http://reactivex.io/documentation/operators/zip.html

Syntax is something like :

Observable.zip ( source 1, source 2, function )

Ex :

const dataNames = Rx.Observable.of(['name1','name2','name3']);
const dataId = Rx.Observable.of([0,2,1]);

Rx.Observable.zip(
   dataId,
   dataNames,
   (arr1,arr2)=> arr1.map(id=> arr2[id])  // change this to your requirement
).subscribe(console.log);
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
Vamshi
  • 9,194
  • 4
  • 38
  • 54