3

I've got a service call that loads ten items onto the screen. When users click a "View More" button, I send another call to the service with different paging arguments. What's the best way to gracefully append the new array of items from the second call into the existing array emitted by the first call?

My example below technically works, but it resets the original observable, refreshing all items on the screen, rather than just adding the new ones. Thoughts? Could Subjects help with this?

private onViewMoreClicked(): void {
    this.pageOffset += this.pageLimit;

    const moreItems$ = this.itemService.get(
        this.pageLimit,
        this.pageOffset
    );

    this.items$ = forkJoin(this.items$, moreItems$).pipe(
        map(([a, b]) => [...a, ...b])
    );
1
  • use trackBy if don't want refresh Commented Dec 10, 2018 at 19:39

2 Answers 2

1

Maybe try something like this or this...

Setup in the on-init…

ngOnInit() {
   this.pageOffset = 0;

    this.items$ = this.nextPage$.pipe(
        // load first batch when Angular async pipe subscribes
        startWith(this.pageOffset),
        // switch observable to output of getMessages
        switchMap(offset => this.itemService.get(
            this.pageLimit,
            offset
        )),
        // add newly-emitted batch to previously-emitted items
        scan((acc, curr) => {
            acc.push(...curr);
            return acc;
        }, [])
    );
}

And this should be the view more click handler…

private onViewMoreClicked(): void {
   this.pageOffset += this.pageLimit;

   // load new items into message$  
    this.nextPage$.next(this.pageOffset);
}
Sign up to request clarification or add additional context in comments.

Comments

-1

With the code you have right now, I think you could do change your forkJoin into this

this.items$ = [...this.items$, ...moreItems$];

But your itemService doesn't look right. I think you want it to be setup something like this

this.itemService(this.pageLimit, this.pageOffset).subscribe(res => {
    this.items$ = [...this.items$, ...res];
});

1 Comment

I see where you're going with this, but for me, subscribing in the component code to the service call to get more items defeats the purpose of using Angular async pipes -- not having to remember to unsubscribe. That's why my service call does not include a subscribe(); Angular will automatically subscribe and unsubscribe with async pipes.

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.