Frontend Integration
On the server side, Picnic receives the grid’s load options, executes the SQL query, and returns a response in the format expected by the frontend library.
On the frontend side, you need to:
- Enable server/remote mode on the grid
- Send the load options to the server
- Pass the response to the grid’s callback
Picnic returns an object that is directly consumable by the grid’s callback — no frontend transformation required.
AG Grid Enterprise (Server-Side Row Model)
jQuery / Vanilla JS
// 1. Enable server mode
var gridOptions = {
rowModelType: 'serverSide',
pagination: true,
paginationPageSize: 20,
cacheBlockSize: 20,
columnDefs: [...]
};
// 2. Datasource
var datasource = {
getRows: function(params) {
jQuery.ajax({
url: '/app/controller?action=loadData',
method: 'POST',
contentType: 'application/json',
data: JSON.stringify(params.request),
success: function(response) {
params.success(response);
},
error: function() {
params.fail();
}
});
}
};
gridApi.setGridOption('serverSideDatasource', datasource);React
import { AgGridReact } from 'ag-grid-react';
function MyGrid() {
const datasource = {
getRows: (params) => {
fetch('/app/controller?action=loadData', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(params.request)
})
.then(res => res.json())
.then(response => params.success(response))
.catch(() => params.fail());
}
};
const onGridReady = (params) => {
params.api.setGridOption('serverSideDatasource', datasource);
};
return (
<AgGridReact
rowModelType="serverSide"
pagination={true}
paginationPageSize={20}
cacheBlockSize={20}
columnDefs={columnDefs}
onGridReady={onGridReady}
/>
);
}Vue 3
<template>
<ag-grid-vue
:rowModelType="'serverSide'"
:pagination="true"
:paginationPageSize="20"
:cacheBlockSize="20"
:columnDefs="columnDefs"
@grid-ready="onGridReady"
/>
</template>
<script setup>
import { AgGridVue } from 'ag-grid-vue3';
const datasource = {
getRows: (params) => {
fetch('/app/controller?action=loadData', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(params.request)
})
.then(res => res.json())
.then(response => params.success(response))
.catch(() => params.fail());
}
};
const onGridReady = (params) => {
params.api.setGridOption('serverSideDatasource', datasource);
};
</script>Angular
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { IServerSideDatasource } from 'ag-grid-community';
@Component({
template: `
<ag-grid-angular
[rowModelType]="'serverSide'"
[pagination]="true"
[paginationPageSize]="20"
[cacheBlockSize]="20"
[columnDefs]="columnDefs"
(gridReady)="onGridReady($event)">
</ag-grid-angular>
`
})
export class MyGridComponent {
constructor(private http: HttpClient) {}
onGridReady(params: any) {
const datasource: IServerSideDatasource = {
getRows: (p) => {
this.http.post('/app/controller?action=loadData', p.request).subscribe({
next: (response) => p.success(response),
error: () => p.fail()
});
}
};
params.api.setGridOption('serverSideDatasource', datasource);
}
}DevExtreme DataGrid / PivotGrid
jQuery / Vanilla JS
// 1. CustomStore with remoteOperations
var customStore = new DevExpress.data.CustomStore({
key: 'id',
load: function(loadOptions) {
var deferred = $.Deferred();
jQuery.ajax({
url: '/app/controller?action=loadData',
method: 'POST',
contentType: 'application/json',
data: JSON.stringify(loadOptions),
success: function(response) {
deferred.resolve(response);
},
error: function(xhr, status, error) {
deferred.reject(error);
}
});
return deferred.promise();
}
});
// 2. Grid with remoteOperations
$('#gridContainer').dxDataGrid({
dataSource: { store: customStore },
remoteOperations: {
paging: true,
sorting: true,
filtering: true,
grouping: true,
summary: true
}
});React
import DataGrid from 'devextreme-react/data-grid';
import CustomStore from 'devextreme/data/custom_store';
function MyGrid() {
const store = new CustomStore({
key: 'id',
load: (loadOptions) => {
return fetch('/app/controller?action=loadData', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(loadOptions)
}).then(res => res.json());
}
});
return (
<DataGrid
dataSource={store}
remoteOperations={{
paging: true,
sorting: true,
filtering: true,
grouping: true,
summary: true
}}
/>
);
}Vue 3
<template>
<DxDataGrid
:data-source="store"
:remote-operations="remoteOps"
/>
</template>
<script setup>
import { DxDataGrid } from 'devextreme-vue/data-grid';
import CustomStore from 'devextreme/data/custom_store';
const store = new CustomStore({
key: 'id',
load: (loadOptions) => fetch('/app/controller?action=loadData', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(loadOptions)
}).then(res => res.json())
});
const remoteOps = {
paging: true,
sorting: true,
filtering: true,
grouping: true,
summary: true
};
</script>Angular
import { Component } from '@angular/core';
import CustomStore from 'devextreme/data/custom_store';
@Component({
template: `
<dx-data-grid
[dataSource]="store"
[remoteOperations]="remoteOps">
</dx-data-grid>
`
})
export class MyGridComponent {
store = new CustomStore({
key: 'id',
load: (loadOptions) => fetch('/app/controller?action=loadData', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(loadOptions)
}).then(res => res.json())
});
remoteOps = {
paging: true,
sorting: true,
filtering: true,
grouping: true,
summary: true
};
}Summary
| Library | Server mode | Options payload | Response |
|---|---|---|---|
| AG Grid | rowModelType: 'serverSide' | params.request (JSON body) | params.success(response) |
| DevExtreme | remoteOperations: { ... } | loadOptions (JSON body) | deferred.resolve(response) |
Supported frameworks: jQuery, React, Vue, Angular (pour AG Grid et DevExtreme).
Last updated on