I'm trying to simulate an http request that supports pagination. For now, this request only returns a number. A parameter of the get request is the page number used in the database.
To be simpler, consider the function getData that returns an observable that returns the page number.
getData(page:number):Observable<number>{
return new Observable<number>(observer => {
observer.next(page)
})
}
Inside my ngOnInit, I declared:
data$!:Observer<number>
page:number = 0
ngOnInit():void{
this.data$ = this.getData(page).pipe(
//RxJS opeartor so that the data:number received will be converted to an array
)
}
I am also trying to code declaratively/reactively by avoiding subscribe() method. So my approach in the template is something like
<div *ngFor="let data of data$ | async"> {{data}} </div>
Lastly, to simulate the "load more" feature, I added <button (click)="loadMore()">Load More</button>
in the template. And in the component,
loadMore():void{
this.data$ = this.getData( this.page).pipe(
//I want to know what should be the RxJS operator that I should use here so that the data<number> that is emitted from the observable, will be appended to this.data$.
)
}
So if I clicked the Load More button 3 times, my template should display
0
1
2
I am open for other approaches as long as it does not use subscribe(). Thank you!
CodePudding user response:
Angular has a subscribe method to work with Observable. I think the easiest way is to use subscribe. Here's an example:
data: any;
loadMore(): void {
this.getData( this.page)
.subscribe(d => {
this.data = d;
});
}
Look all the changes that I did first. Check the data variable is now type any, because I don't know what is your data response type. Let me know if it works for you.
CodePudding user response:
In rxjs the standard operator to convert observable data is map.
usage is simple, and similar to Array.map
:
loadMore():void{
this.data$ = this.getData( this.page).pipe(
map(dataIn => ({ dataIn, page: this.page }))
)
}
As you pointed out, it is not good practice to subscribe to observables from the component (it might lead you into the memory-leak trap).
Instead of subscribing you should return an observable (or set a variable with the observable as you did) and use the async pipe from the views to extract its values (it subscribes/uinsubscrives as necessary, which voids the issues):
<div>{{ (data$ | async)?.page }}</div>