1

I have an Observable where User has an array property Posts[] that I want to iterate through, invoke a method with the intermediate values and then return an Observable with the resulting objects as arrays.

At the moment I have the following code that works:

    public ngOnInit() {
    const results: any[] = [];
    this.controlData$ = this.controlContent$
        .pipe(
            filter((input) => input !== null),
            flatMap((p: IControlContentSection) => p.controlPerformers),
            map((m: IControlPerformer) => {
                results.push({
                        ...m,
                        nextOccurrence: this.getNextControlDate(m.controlFrequency, m.firstOccurrence),
                    });
                return results;
                }),
            takeUntil(this.destroy$),
            );
}

I use an array variable results: any[], but I do not like this solution as it relies on this external variable, making it working only when the component is initialized.

I tried to use toArray() or a reduce((x, y) => x.concat(y), []) after the map, but this then resolves into null in the template.

How can I return an Observable without the need of an external variable?

In template I subscribe via async pipe:

<div *ngIf="controlData$ | async as controllers">
  ...
  <div *ngFor="let ctrl of controllers; trackBy:ctrl?.userId">
  ...
  </div>
</div>

1 Answer 1

1

You are doing it correctly after the map, it should work. But to simulate your exact behavior you need a scan operator. The scan operator will emit intermediate values, as you do returning your results array. Have you tried it like this?:

 public ngOnInit() {
    this.controlData$ = this.controlContent$
    .pipe(
        filter((input) => input !== null),
        flatMap((p: IControlContentSection) => p.controlPerformers),
        map((m: IControlPerformer) => {
            return {...m,
                    nextOccurrence: this.getNextControlDate(m.controlFrequency, m.firstOccurrence),
                };
         }),
         scan((acc, cur) => [...acc, cur], [])
         takeUntil(this.destroy$),
        );
}

It should work, if not, I could provide you a plunker or so.

Hope this helps.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Llorenc, using scan indeed works, returning an Observable of array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.