Goal is to be able to set filter values, sorting and column states without causing multiple get rows requests. Also, there should be a possibility to pre-set a grid before a first get rows request is send to a server.
Ag-Grid has limited options to do such a thing. There is GridOptions.columnDefs
property which allows to initialise sorting of any column and to set its state, unfortunately there are no such properties for filters.
On the other hand GridOptions.columnApi.setColumnState()
, GridOptions.api.setFilterModel()
and GridOptions.api.setSortModel()
methods allows to do such task, but some of those methods cause rows to be reloaded from a server which leads to multiple server calls and unnecessary data transfer.
Solution
After examining ag-Grid's code I have found that easiest way to accomplish this is to just ignore some of the endpoint calls. For example setting a filter model and a sort model cause two endpoint calls. So first call will be ignored.
@Component(...)
export class AgGridComponent implements OnInit, AfterViewInit {
@ViewChild('agGrid')
private agGrid: AgGridAngular;
private service: AgGridService;
constructor(private httpClient: HttpClient) {
}
ngOnInit() {
this.service = new AgGridService(this.agGrid, this.entityClassName, this.httpClient);
}
ngAfterViewInit() {
this.service.initGrid();
}
// User wants to set filters, sorting, etc. to a different set of values.
selectLayout(gridLayout: GridLayout) {
this.service.selectLayout(gridLayout);
}
}
class AgGridService implements IServerSideDatasource {
private requestsToIgnore = 0;
constructor(private agGrid: AgGridAngular, private httpClient: HttpClient) {
}
initGrid(): void {
this.httpClient.get('get-grid-config').subscribe((gridConfig: GridConfig) => {
// We have a grid configuration so let's set grid up. Methods setServerSideDatasource(),
// setFilterModel() and setSortModel() cause get-rows endpoint to be called, so we have
// to ignore two of those three calls.
this.requestsToIgnore = 2;
const gridOptions = this.agGrid.gridOptions;
gridOptions.api.setColumnDefs(gridConfig.columnDefs);
// Method setServerSideDatasource() resets any filter or sort models so it has to be
// called first.
gridOptions.api.setServerSideDatasource(this);
gridOptions.columnApi.setColumnState(gridConfig.defaultGridLayout.columnState);
gridOptions.api.setFilterModel(gridConfig.defaultGridLayout.filterModel);
gridOptions.api.setSortModel(gridConfig.defaultGridLayout.sortModel);
});
}
selectLayout(gridLayout: GridLayout): void {
// In this case we have to ignore only one call.
this.requestsToIgnore = 1;
const gridOptions = this.agGrid.gridOptions;
gridOptions.columnApi.setColumnState(gridLayout.columnState);
gridOptions.api.setFilterModel(gridLayout.filterModel);
gridOptions.api.setSortModel(gridLayout.sortModel);
}
getRows(params: IServerSideGetRowsParams): void {
if (this.requestsToIgnore-- > 0) {
params.failCallback();
} else {
this.httpClient.post('get-rows', params.request).subscribe(
(rows: any) => params.successCallback(rows.data, rows.lastRow),
() => params.failCallback()
);
}
}
destroy(): void {
}
}
interface GridConfig {
columnDefs: (ColDef | ColGroupDef)[]
defaultGridLayout: GridLayout,
gridLayouts: GridLayout[]
}
interface GridLayout {
columnState: any,
filterModel: any,
sortModel: any
}
Rationale
In ag-Grid's column.ts.Column.constructor()
, you can clearly see that there are not too many possibilities to preinitialise a column's state. There are a few properties for sorting and showing/hiding a column, but there is no such a thing like pre-setting filter values.
Filter values can be set by GridOptions.api.setFilterModel()
method, which internally raises two model-updated events. Model-updated event leads to a server request. Actually these two events leads to a single request because second event is swallowed in serverSideCache.ts.ServerSideCache.getRow()
method.
There has been call for this functionality to be implemented in ag-Grid's init phase, unfortunately the feature request was closed without proper solution.