Search code examples
angularrxjsrxjs5rxjs6

How to append an Observable array to existing one consumed via Angular async pipes?


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])
    );

Solution

  • 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);
    }