DevExtreme jQuery - Custom Sources
The DataGrid uses the CustomStore to receive data from a custom source. This article provides details on how to configure it and the protocol that the CustomStore adheres to when communicating with the server. If the server already processes data, that is, performs filtering, sorting, paging, grouping or summary calculation, notify the DataGrid by assigning true to the corresponding remoteOperations object field.
jQuery
$(function() { $("#gridContainer").dxDataGrid({ // ... remoteOperations: { filtering: true, sorting: true, paging: true, grouping: true, summary: true } // or simply // remoteOperations: true }); });
Angular
<dx-data-grid ... > <dxo-remote-operations [filtering]="true" [sorting]="true" [grouping]="true" [paging]="true" [summary]="true"> </dxo-remote-operations> <!-- or simply --> <!-- [remoteOperations]="true" --> </dx-data-grid>
import { DxDataGridModule } from 'devextreme-angular'; // ... export class AppComponent { // ... } @NgModule({ imports: [ // ... DxDataGridModule ], // ... })
If the server does not process data yet, employ one of the following DevExtreme extensions. They implement server-side data processing and also configure the CustomStore. Remember to notify the DataGrid of the data processing operations that were delegated to the server.
If these extensions do not suit your needs, configure the CustomStore and implement server-side data processing by following the instructions in this article. Note that the server may leave some of the data processing operations unimplemented. In this case, make sure that the corresponding remoteOperations object fields are set to false.
See Also
Load Data
The CustomStore needs the load function to load data from the server. This function accepts a collection of loadOptions and passes them to the server. The server then processes data according to the loadOptions and sends it back. The following loadOptions are relevant for the DataGrid:
take: Number
Restricts the number of top-level data objects to return.skip: Number
Skips some data objects from the start of the result set. In conjunction with take, this parameter is used to implement paging.sort: Array
Defines sorting parameters. Multiple parameters apply to the data in sequence to implement multi-level sorting. Contains objects of the following structure:{ selector: "field", desc: true/false }
filter: Array
Defines filtering parameters. Possible variants:Binary filter
[ "field", "=", 3 ]
Unary filter
[ "!", [ "field", "=", 3 ] ]
Complex filter
[ [ "field", "=", 10 ], "and", [ [ "otherField", "<", 3 ], "or", [ "otherField", ">", 11 ] ] ]
See the Filtering topic for more details.
requireTotalCount: Boolean
Indicates that a total count of data objects in the result set must be returned in the totalCount field of the result. This count must reflect the number of data items after filtering, but disregard any take parameter used for the query.totalSummary: Array
Contains summary definitions of the following structure, where summaryType can be "sum", "avg", "min", "max" or "count":{ selector: "field", summaryType: "sum" }
The summary calculations' results should be returned in an array called summary that contains the result values in the same order as the summary definitions.
group: Array
Defines grouping levels to be applied to the data. Each object can have the following parameters:- selector: String
The field name to group by. - desc: Boolean
Defines the selector field's descending sort order. - isExpanded: Boolean
Defines whether the group's data objects should be returned instead of grouping data. Relevant only for the last group. - groupInterval: Number or String
A numeric value groups data in ranges of the given length. A string value applies only to dates and can be one of "year", "quarter", "month", "day", "dayOfWeek", "hour", "minute" and "second". This parameter is present only when the widget sends a request for the header filter's data, and only if this data contains numbers or dates. Note that for numbers, the groupInterval option should be specified explicitly.
- selector: String
groupSummary: Array
The structure is the same as for totalSummary, but these summary values are returned for each group. Used in conjunction with group.
After receiving these settings, the server should apply them to data and send back an object of the following structure:
{ data: [{ key: "Group 1", items: [ ... ], // subgroups or data objects (for the last group when isExpanded = true) // can be null when isExpanded = false and there are no further groups count: 3, // count of items in this group; required only when items is null summary: [30, 20, 40] // group summary results }, ... ], totalCount: 200, // if required in requireTotalCount summary: [170, 20, 20, 1020] // total summary results }
If the server has not received the group parameter, the result object should be the following:
{ data: [ ... ], // result data objects totalCount: 200, // if required in requireTotalCount summary: [170, 20, 20, 1020] // total summary results }
Here is a generalized configuration of the CustomStore for the DataGrid widget.
jQuery
var gridDataSource = new DevExpress.data.DataSource({ load: function (loadOptions) { var d = $.Deferred(); $.getJSON('http://mydomain.com/MyDataService', { skip: loadOptions.skip, take: loadOptions.take, sort: loadOptions.sort ? JSON.stringify(loadOptions.sort) : "", filter: loadOptions.filter ? JSON.stringify(loadOptions.filter) : "", requireTotalCount: loadOptions.requireTotalCount, totalSummary: loadOptions.totalSummary ? JSON.stringify(loadOptions.totalSummary) : "", group: loadOptions.group ? JSON.stringify(loadOptions.group) : "", groupSummary: loadOptions.groupSummary ? JSON.stringify(loadOptions.groupSummary) : "" }).done(function (result) { d.resolve(result.data, { totalCount: result.totalCount, summary: result.summary }); }); return d.promise(); } }); $(function() { $("#dataGridContainer").dxDataGrid({ dataSource: gridDataSource, remoteOperations: true }); });
Angular
import { ..., Inject } from '@angular/core'; import { Http, HttpModule, URLSearchParams } from '@angular/http'; import { DxDataGridModule } from 'devextreme-angular'; import DataSource from 'devextreme/data/data_source'; import CustomStore from 'devextreme/data/custom_store'; import 'rxjs/add/operator/toPromise'; // ... export class AppComponent { gridDataSource: any = {}; constructor(@Inject(Http) http: Http) { this.gridDataSource = new DataSource({ load: function (loadOptions) { let params: URLSearchParams = new URLSearchParams(); params.set("skip", loadOptions.skip); params.set("take", loadOptions.take); params.set("sort", loadOptions.sort ? JSON.stringify(loadOptions.sort) : ""); params.set("filter", loadOptions.filter ? JSON.stringify(loadOptions.filter) : ""); params.set("requireTotalCount", loadOptions.requireTotalCount); params.set("totalSummary", loadOptions.totalSummary ? JSON.stringify(loadOptions.totalSummary) : ""); params.set("group", loadOptions.group ? JSON.stringify(loadOptions.group) : ""); params.set("groupSummary", loadOptions.groupSummary ? JSON.stringify(loadOptions.groupSummary) : ""); return http.get('http://mydomain.com/MyDataService', { search: params }) .toPromise() .then(response => { var json = response.json(); // You can process the received data here return { data: json.data, totalCount: json.totalCount, summary: json.summary } }); } }); } } @NgModule({ imports: [ // ... DxDataGridModule, HttpModule ], // ... })
<dx-data-grid ... [dataSource]="gridDataSource" [remoteOperations]="true"> </dx-data-grid>
Consider using the remote group paging feature when grouping large data lowers DataGrid performance. Note that for this feature, both the server and the client sides should be configured differently. Refer to the Remote Group Paging topic for more information.
Add, Delete, Update Data
To allow a user to add, delete and update data in the DataGrid, assign true to the corresponding field of the editing object.
jQuery
$(function(){ $("#gridContainer").dxDataGrid({ // ... editing: { allowUpdating: true, allowDeleting: true, allowAdding: true } }); });
Angular
<dx-data-grid ... > <dxo-editing [allowUpdating]="true" [allowDeleting]="true" [allowAdding]="true"> </dxo-editing> </dx-data-grid>
import { DxDataGridModule } from 'devextreme-angular'; // ... export class AppComponent { // ... } @NgModule({ imports: [ // ... DxDataGridModule ], // ... })
With these settings, the DataGrid expects that the server can also add, update and delete data. In addition, you need to configure the CustomStore as shown below. Note that in this example, the CustomStore is not declared explicitly. Instead, CustomStore operations are implemented directly in the DataSource configuration object to shorten the example.
jQuery
var gridDataSource = new DevExpress.data.DataSource({ // ... insert: function (values) { return $.ajax({ url: "http://mydomain.com/MyDataService/", method: "POST", data: values }) }, remove: function (key) { return $.ajax({ url: "http://mydomain.com/MyDataService/" + encodeURIComponent(key), method: "DELETE", }) }, update: function (key, values) { return $.ajax({ url: "http://mydomain.com/MyDataService/" + encodeURIComponent(key), method: "PUT", data: values }) } }); $(function() { $("#gridContainer").dxDataGrid({ dataSource: gridDataSource, // ... }); });
Angular
import { ..., Inject } from '@angular/core'; import { Http, HttpModule, URLSearchParams } from '@angular/http'; import { DxDataGridModule } from 'devextreme-angular'; import DataSource from 'devextreme/data/data_source'; import CustomStore from 'devextreme/data/custom_store'; import 'rxjs/add/operator/toPromise'; // ... export class AppComponent { gridDataSource: any = {}; constructor(@Inject(Http) http: Http) { this.gridDataSource = new DataSource({ // ... insert: function (values) { return http.post('http://mydomain.com/MyDataService', values) .toPromise(); }, remove: function (key) { return http.delete('http://mydomain.com/MyDataService' + encodeURIComponent(key)) .toPromise(); }, update: function (key, values) { return http.put('http://mydomain.com/MyDataService' + encodeURIComponent(key), values) .toPromise(); } }); } } @NgModule({ imports: [ // ... DxDataGridModule, HttpModule ], // ... })
<dx-data-grid ... [dataSource]="gridDataSource"> </dx-data-grid>
See Also
If you have technical questions, please create a support ticket in the DevExpress Support Center.