How to implement server-side Pagination + server-side Sorting with ngx-datatable
I figure out that the best way to handle both server-side pagination AND server-side sorting consist of:
having a
page
object which holds all the pagination and sorting information (like the order column, order direction, page number, page size, ...) which will be bound to the tablehaving a single function
reloadTable()
which calls the API to get the data using the data stored in thepage
object as parameters, automaticaly re-rendering the tablehaving a
pageCallback
which only updates the data contained inpage
relative to the pagination and then callsreloadTable()
having a
sortCallback
which only updates the data contained inpage
relative to the sorting and then callsreloadTable()
example:
import { Component, OnInit } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
@Component({
selector: 'app-my-component',
template: `
<ngx-datatable
class="bootstrap table table-striped"
[rows]="rows"
[columns]="columns"
[columnMode]="'force'"
[headerHeight]="50"
[footerHeight]="50"
[rowHeight]="'auto'"
[externalPaging]="true"
[externalSorting]="true"
[count]="page.count"
[offset]="page.offset"
[limit]="page.limit"
[sortType]="'single'"
(page)="pageCallback($event)"
(sort)="sortCallback($event)"
></ngx-datatable>
`
})
export class MyComponent implements OnInit {
page = {
limit: 10,
count: 0,
offset: 0,
orderBy: 'myColumn1',
orderDir: 'desc'
};
rows: Object[];
columns = [
{ name: 'myColumn1' },
{ name: 'myColumn2' },
{ name: 'myColumn3' },
];
constructor(private httpClient: HttpClient) { }
ngOnInit() {
this.pageCallback({ offset: 0 });
}
/**
* Called whenever the user changes page
*
* check: https://swimlane.gitbooks.io/ngx-datatable/content/api/table/outputs.html
*/
pageCallback(pageInfo: { count?: number, pageSize?: number, limit?: number, offset?: number }) {
this.page.offset = pageInfo.offset;
this.reloadTable();
}
/**
* Called whenever the user changes the sort order
*
* check: https://swimlane.gitbooks.io/ngx-datatable/content/api/table/outputs.html
*/
sortCallback(sortInfo: { sorts: { dir: string, prop: string }[], column: {}, prevValue: string, newValue: string }) {
// there will always be one "sort" object if "sortType" is set to "single"
this.page.orderDir = sortInfo.sorts[0].dir;
this.page.orderBy = sortInfo.sorts[0].prop;
this.reloadTable();
}
/**
* You will render the table once at the beginning in ngOnInit()
* and then every time the page OR the sort order are changed
*/
reloadTable() {
// NOTE: those params key values depends on your API!
const params = new HttpParams()
.set('orderColumn', `${this.page.orderBy}`)
.set('orderDir', `${this.page.orderDir}`)
.set('pageNumber', `${this.page.offset}`)
.set('pageSize', `${this.page.limit}`);
this.httpClient.get(`http://www.your-api.com/path/resource`, { params })
.subscribe((data) => {
// NOTE: the format of the returned data depends on your API!
this.page.count = data.count;
this.rows = data.rows;
});
}
}
Comments
-
Francesco Borzi about 2 years
With the Angular component ngx-datatable from Swilane it is possible to use the server-side paging and the server-side sorting.
Both of them are documented, however it is not clear how to combine them and use server side pagination+sorting at the same time.
From the documentation, the pagination automatically calls a callback when the user changes page:
setPage(pageInfo) { this.page.pageNumber = pageInfo.offset; this.serverResultsService.getResults(this.page).subscribe(pagedData => { this.page = pagedData.page; this.rows = pagedData.data; });
and the same happens with the sorting:
onSort(event) { // event was triggered, start sort sequence console.log('Sort Event', event); this.loading = true; // emulate a server request with a timeout setTimeout(() => { const rows = [...this.rows]; // this is only for demo purposes, normally // your server would return the result for // you and you would just set the rows prop const sort = event.sorts[0]; rows.sort((a, b) => { return a[sort.prop].localeCompare(b[sort.prop]) * (sort.dir === 'desc' ? -1 : 1); }); this.rows = rows; this.loading = false; }, 1000); }
but how to combine them?