Отображение одной сущности ngrx в цикле ngFor с использованием идентификаторов

Я использую NG6 с NGRX для отображения двух наборов данных в представлении. Первый набор данных - это полный набор данных. Второй набор данных является подмножеством первого набора данных.

Мне нужно использовать цикл ngFor во втором наборе данных, который обеспечивает idи внутри цикла используйте id чтобы отобразить одну сущность из первого набора данных.

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>

В этом представлении правильно отображаются оба подмножества, имена и идентификаторы (числа)

subData.id соответствует имени в datasetOne, я хочу отобразить имя вместо id

Это что-то вроде этого для представления:

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

но мне не удалось написать метод, который может получить один объект из datasetOne$

2 ответа

Решение

Поскольку вы уже используете селекторы, я бы предложил создать новый селектор на основе текущих двух.

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

Если это невозможно, вы также можете сделать следующее, как указано в NgRx: Параметризованные селекторы

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

В основном у вас есть два потока, и вы хотите создать новый поток, используя значения из обоих. Вам нужно использовать zip

Документ: http://reactivex.io/documentation/operators/zip.html

Синтаксис что-то вроде:

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

Пример:

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>

Другие вопросы по тегам