6

I have showing youtube videos by using async pipe in Angular 6. It's working fine for the first load.

This is how am using it.

Component HTML file:

<div id="youtube" class="search-results" *ngIf="(trendingVideos | async) as videos; else loadingOrError"></div>

Component TS file:

public trendingVideos: Observable<VideoClass[]>;
private loadVideos(videosPerPage?: number, regionCode?: string, videoCategoryId?: number) {
      this.trendingVideos = this.youtubeService.getTrendingVideos(videosPerPage, regionCode, videoCategoryId, false)
        .pipe(
          catchError((error: any) => {
            this.loadingError$.next(true);
            return throwError(error);
          })
        );
  }

Catch error is working fine also.

Service File:

public getTrendingVideos(videosPerPage?: number, regionCode?: string, videoCategoryId?: number, paginationMode?: boolean): Observable<VideoClass[]> {
    const params: any = {
      part: appConfig.partsToLoad,
      chart: appConfig.chart,
      videoCategoryId: videoCategoryId ? videoCategoryId : appConfig.defaultCategoryId,
      regionCode: regionCode ? regionCode : appConfig.defaultRegion,
      maxResults: videosPerPage ? videosPerPage : appConfig.maxVideosToLoad,
      key: appConfig.youtubeApiKey
    };
    return this.http.get<any>(appConfig.getYoutubeEndPoint('videos'), { params })
      .pipe(
        map(
          (data) => {
            return data.items
              .map((item) => new VideoClass(item))
              .filter((item) => item.id !== '');
          }
        ),
        catchError(this.handleError('getTrendingVideos'))
      ) as Observable<VideoClass[]>;
  }

It's working fine when I load data the first time. Now I am developing infinite scroll. So I am calling this API again. But want to merge data into previously loaded data.

It replaces the data every time with new data when my infinite scroll plugin calls this.

This is infinite scroll function:

private onScroll(){
    let videosData:Observable<VideoClass[]> = this.youtubeService.getTrendingVideos(this.videoCount, this.regionCode, this.categoryID, true)
    .pipe(
      catchError((error: any) => {
        this.loadingError$.next(true);
        return throwError(error);
      })
    );
    // Here how i merge this same video data to previously loaded trending videos data.
  }

Any Help?

5
  • 1
    Try creating an array of VideoClass and append the result of api in that array. Use the samearray to display data in html. Commented Oct 29, 2018 at 11:40
  • How i am going to use async pipe with that. @SarthakAggarwal Commented Oct 29, 2018 at 11:46
  • You can just use *ngIf to check if length of array is 0. If its 0, it means the data is yet to be retrieved from api. if length > 0, you can display the data and on further scrolling, you can call your api and append the data in same array. Commented Oct 29, 2018 at 11:50
  • Any way to do using async pipe. @SarthakAggarwal Commented Oct 29, 2018 at 11:51
  • 2
    In rxjs, if you want to add to the previously returned results, you want to use the scan or mergeScan operator Commented Oct 29, 2018 at 14:25

2 Answers 2

1

You just have to use the rxjs map operator and return a new array inside, something like this in your case :

EDIT:

Use a behavior subject to get newly videos retrieve by api call.

Here is a live example: Stackblitz

component.ts

private videos = [];
private newVideos$ = new BehaviorSubject<VideoClass[]>([]);
public trendingVideos: Observable<VideoClass[]>;

ngOnInit(){
   this.trendingVideos = this.newVideos$.pipe(
     filter(data => data.length > 0),
     map(data => {
        this.videos = [...this.videos, ...data];
        return this.videos;
     });
}
private loadVideos(videosPerPage?: number, regionCode?: string, videoCategoryId?: number) {
  this.youtubeService.getTrendingVideos(videosPerPage, regionCode, videoCategoryId, false)
    .pipe(
      catchError((error: any) => {
        this.loadingError$.next(true);
        return throwError(error);
      })
    ).subscribe(newVideos => this.newVideos$.next(newVideos));
}

Hope it helps!

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

2 Comments

It's stop calling API. If I remove map then it starts calling API.
@KPrananv I updated my answer and add a basic live example on Stackblitz.
1

Modify Your Infinite scroll as:

private onScroll(bufferObj$) {
    return zip(bufferObj$, this.youtubeService.getTrendingVideos(this.videoCount, this.regionCode, this.categoryID, true)
    .pipe(
        catchError((error: any) => {
            this.loadingError$.next(true);
            return throwError(error);
        })
    )).pipe(map((x: any) => x[0].concat(x[1])));
}

Comments

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.