I have a mat-table element and a mat-paginator
element below.
The table is filled with data from API.
My API returns 10 elements by request by default, but I need to display 25 elements in my table, hence I need to make 3 API requests to fill the mat-table.
How to repeat the call to API, with different argument and then return combined all three responses into one observable?
In my case - I want to repeat getPlanetsPage(pageNumber)
with different pageNumber
, so this is the tricky part (I tried to solve this by repeat()
...):
return this.planetService.getPlanetsPage(dontKnowHowToDoItArg)
.pipe(
repeat(Math.ceil(this.paginator.pageSize / this.countOfPlanetsPerPage))
);
Whole code from ngAfterViewInit() :
this.paginator.page
.pipe(
startWith({}),
switchMap((paginatorData) => {
this.isLoadingResults = true;
const indexOfFirstElementToRenderInTable = this.paginator.pageSize * this.paginator.pageIndex;
if (this.planets[indexOfFirstElementToRenderInTable]) {
this.planetsToRender = this.planets.slice(indexOfFirstElementToRenderInTable, this.paginator.pageSize * (this.paginator.pageIndex + 1));
return EMPTY;
} else {
return this.planetService.getPlanetsPage(dontKnowHowToDoItArg)
.pipe(
repeat(Math.ceil(this.paginator.pageSize / this.countOfPlanetsPerPage))
);
}
}),
map(planetsPage => {
this.isLoadingResults = false;
this.isRateLimitReached = false;
this.resultsLength = planetsPage.count;
return planetsPage.results;
}),
catchError(() => {
this.isLoadingResults = false;
this.isRateLimitReached = true;
return of([]);
})
).subscribe((planetsArr: Planet[]) => {
this.planets.push(...planetsArr);
const indexOfFirstElementToRenderInTable = this.paginator.pageSize * this.paginator.pageIndex;
this.planetsToRender = this.planets.slice(indexOfFirstElementToRenderInTable, this.paginator.pageSize * (this.paginator.pageIndex + 1));
this.requestNo++;
});
http service get method:
getPlanetsPage(pageNumber): Observable<any> {
return this.httpClient.get(this.planetsBasicPageUrl, {
params: new HttpParams()
.set('page', pageNumber.toString())
});
}
There is an rxjs operator dedicated for recursive calls, check EXPAND. Here is what will work for you
import { from, EMPTY } from 'rxjs';
import { expand, tap, switchMap } from 'rxjs/operators';
...
let results = [] // to concatenate your data each time
let pageNumber = 1; // to count your calls, you need 3 calls so it will be your stop condition
getPlanetsPage(pageNumber): Observable<any> {
return this.httpClient.get(this.planetsBasicPageUrl, {
params: new HttpParams()
.set('page', pageNumber.toString())
});
}
getPlanetsPage(1).pipe(
tap(res => {
this.pageNumber++;
results = results.concat(res) // on success add new results to our array
}),
expand((_) => this.pageNumber <=3
? getPlanetsPage(this.pageNumber)
: EMPTY;
)
).subscribe(console.log)
it's short and clean, you can check my post on dev.to about recursive calls https://dev.to/fatehmohamed14/recursive-http-calls-the-rxjs-way-d61
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With