Reputation: 15
Is there a way to keep my last posts from the first call to not being overwritten by the next call of the same function?
In other words , I have an API route like this:
{{url}}?/page=1&limit=3
// page represents a param that i can manipulate incoming posts;
// limit represents how many posts will show with the call;
This route returns me 3 posts , but after I change page=2
I get the next 3 posts from all posts and my previous posts gets overwritten..
UPDATED AGAIN
//this is the service for getting posts;
allPosts$;
isLastPage = false;
currentPage = 0;
pageNumberSubject = new BehaviorSubject<number>(1);
pageSizeAction$ = this.pageNumberSubject.asObservable();
getSimplePosts(): Observable<any[]> {
return this.pageSizeAction$.pipe(
concatMap((pgNum: number): Observable<SimplePosts[]> =>
this.http.get<SimplePosts[]>(this._allPostsAPI, {
params: {
page: pgNum.toString(),
limit: "3"
}
})
),
scan((allPosts: SimplePosts[], pageUsers: SimplePosts[]) => [...allPosts, pageUsers], []),
tap((posts: SimplePosts[]) => console.log(JSON.stringify(posts))))
}
nextPage() {
this.currentPage += 1;
this.pageNumberSubject.next(this.currentPage);
}
// old implementation;
getAllPosts(page, limit) {
return this.http.get(`${this._allPostsAPI}?page=${page}&limit=${limit}`, httpOptions);
}
How can I use it in my component ?? I can't implement the function right in my component because I have tokens bypass and they get along in service..
This is very hard really.. i spent so many hours trying to figure out , but its too challenging for me right now.. I will rollback everything for now. If I will find a way to do this I will sure update this for everyone that needs it.
//this is the component where I use the infinite scroll;
personSubject = new BehaviorSubject<any>(null);
person$: Observable<any> = this.personSubject.asObservable();
private destroy$ = new Subject();
constructor(){
//first initialise posts as first page ,
//then after the user scrolls down it activates the doInfinite() function;
this.authService.getSimplePosts().pipe(takeUntil(this.destroy$))
.subscribe((res: any) => {
console.log(res);
res.map((simplePosts: any) => {
console.log(simplePosts);
this.personSubject.next(simplePosts.data.post);
this.userGallery = simplePosts.data.post.forEach(imgIndex => {
imgIndex.galleryImages = imgIndex.images.map((image: any, index: number) => {
return new Image(
index,
{ //modal
img: image,
extUrl: image,
title: image,
},
)
});
});
});
})
}
doInfinite(infiniteScroll) {
setTimeout(() => {
console.log(this.allPosts$);
//here i call the function and it works , but my observables are still gone :D
this.authService.nextPage();
this.authService.getSimplePosts().pipe(takeUntil(this.destroy$), share()).subscribe((res: any) => {
console.log(res);
res.map((simplePosts: any) => {
console.log(simplePosts);
this.personSubject.next(simplePosts.data.post);
this.userGallery = simplePosts.data.post.forEach(imgIndex => {
imgIndex.galleryImages = imgIndex.images.map((image: any, index: number) => {
return new Image(
index,
{ //modal
img: image,
extUrl: image,
title: image,
},
)
});
});
});
})
console.log(infiniteScroll)
infiniteScroll.target.complete();
}, 1000);
}
** EDITED; ** This is the final stage , I did as your stackblitz , but after i scroll down , my observables gets overwritted and the page doesnt concatenate , it calls the same page again. Help?!
Upvotes: 1
Views: 761
Reputation: 60558
You could use scan()
and add the newly retrieved items to an array of retained items. You'd need to be careful though because if you are re-retrieving as the user navigates around in the application, you could end up with duplicate information in that retained array.
UPDATE:
The following demonstrates how to use the scan
operator with paging.
NOTE: This makes the assumption that pages are advanced sequentially with no going backwards or skipping pages.
allPosts$ = this.pageSizeAction$.pipe(
concatMap(page =>
this.http.get<Post[]>(this.postUrl, {
params: {
_page: page.toString(),
_limit: "2"
}
})
),
scan((acc, value) => [...acc, ...value])
);
The scan takes in the accumulated value (acc
), which starts with the first set of retrieved data by default. And it takes in the newly retrieved value (value
). So this uses array spread syntax to spread the values of each array (the original and the newly retrieved set) into a new array.
You can find a working stackblitz here: https://stackblitz.com/edit/angular-paging-api-deborahk
Upvotes: 5