HARI PRASAD
HARI PRASAD

Reputation: 123

Angular - Passing Array of Observables as @Input

I'm trying a replace a current NGRX implmentation of binding data in template to reusable component due to change in dataStructure of @Input.

HTML:
//replace
"<child [summary]="summaryTitle$ | async" ></child >"

//with
"<child  [summary]="summaryTitles" ></child>"
parent.comp.ts
//replace
summaryTitle$ = this.store.select(Title)

//with
summaryTitles = [{title:summaryTitle$ , text: "someConstantValue"},...]

Here I need to resolve the summaryTitles array before passing it to the <child>, any easy method to do so like using async pipe for single result.

the Idea is to re-use the existing <child> without making much changes and I wont able to add any changes to the @store as well

Upvotes: 0

Views: 300

Answers (1)

Stav Noy
Stav Noy

Reputation: 519

Edit: If text is never an observable:

const result$ = combineLatest(
  summaryTitles.map(({ title, text }) => 
    title.pipe(map(title => ({ title, text })));
  )
);

A minimal reproducible example with something like stackblitz would be good, it's a pain to reproduce ngrx state and all, but something like this should work:

import { of, map, combineLatest } from 'rxjs';

const summaryTitles = [
  { title: of('1'), text: of('2') },
  { title: of('3'), text: of('4') }
];

const result$ = combineLatest(
  summaryTitles.map(({title, text}) =>
    combineLatest([title, text]).pipe(
      map(([title, text]) => ({ title, text }))
    )
  )
);

result$.subscribe(console.log);

You may want to change combineLatest for forkJoin or zip. The doc's operator decision tree and learnrxjs.io are great for that.

Stackblitz: https://stackblitz.com/edit/rxjs-9gah4b?file=index.ts

Edit: If the text field may be an observable or not, use isObservable, for example:

const result$ = combineLatest(
  summaryTitles.map(({ title, text }) => {
    const text$ = isObservable(text) ? text : of(text);
    return combineLatest([title, text$]).pipe(
      map(([title, text]) => ({ title, text }))
    );
  })
);

But it may be easier to insure it's an observable somewhere else before that.

Side note: I noticed now in my stackblitz the final result, which shouold be an array, is an "indexed object" ({ 0: 'foo', 1: 'bar' }). When I try to manually transform it to an array in ways that work in terminal it remains an object 🤷. I'm assuming this is a quirk in stackblitz. Check what you get live.

Upvotes: 1

Related Questions