When a datasource load fails, call retryServerSideLoads() to reload the failed rows at a later time.
When loading fails, the datasource informs the grid of such using the fail() callback instead of using the success() callback. Calling fail() puts the loading rows into a Loading Failed state which hides the loading spinner. No data is shown in these rows as they are not loaded.
Failed loads can be retried by using the grid API retryServerSideLoads(). This will retry all loads that have previously failed.
Gets all failed server side loads to retry. |
Examples Copy Link
The following example demonstrates load retrying. Note the following:
When the checkbox 'Make Loads Fail' is checked, all subsequent loads will fail, i.e. the Datasource will call
fail()instead ofsuccess(). Try checking the checkbox and expand a few groups to observe failed loading.When the button 'Retry Failed Loads' is pressed, any loads which were marked as failed are retried.
When the button 'Reset Entire Grid' is pressed, the grid will reset. This allows you to have 'Make Loads Fail' checked while starting from scratch, thus failing loading of the top level of rows.
import {
GridApi,
GridOptions,
IServerSideDatasource,
ModuleRegistry,
createGrid,
enableDevValidations,
} from "ag-grid-community";
import {
RowGroupingModule,
ServerSideRowModelApiModule,
ServerSideRowModelModule,
} from "ag-grid-enterprise";
import { FakeServer } from "./fakeServer";
import { IOlympicData } from "./interfaces";
// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
enableDevValidations();
}
ModuleRegistry.registerModules([
RowGroupingModule,
ServerSideRowModelModule,
ServerSideRowModelApiModule,
]);
let gridApi: GridApi<IOlympicData>;
const gridOptions: GridOptions<IOlympicData> = {
columnDefs: [
{
// demonstrating the use of valueGetters
colId: "country",
valueGetter: "data.country",
rowGroup: true,
hide: true,
},
{ field: "sport", rowGroup: true, hide: true },
{ field: "year", minWidth: 100 },
{ field: "gold", aggFunc: "sum" },
{ field: "silver", aggFunc: "sum" },
{ field: "bronze", aggFunc: "sum" },
],
defaultColDef: {
flex: 1,
minWidth: 120,
},
autoGroupColumnDef: {
flex: 1,
minWidth: 280,
field: "athlete",
},
// use the server-side row model
rowModelType: "serverSide",
maxConcurrentDatasourceRequests: 1,
suppressAggFuncInHeader: true,
purgeClosedRowNodes: true,
cacheBlockSize: 20,
};
function getServerSideDatasource(server: any): IServerSideDatasource {
return {
getRows: (params) => {
console.log("[Datasource] - rows requested by grid: ", params.request);
const response = server.getData(params.request);
// adding delay to simulate real server call
setTimeout(() => {
if (response.success) {
// call the success callback
params.success({
rowData: response.rows,
rowCount: response.lastRow,
});
} else {
// inform the grid request failed
params.fail();
}
}, 1000);
},
};
}
function onBtRetry() {
gridApi!.retryServerSideLoads();
}
function onBtReset() {
gridApi!.refreshServerSide({ purge: true });
}
const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);
fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
.then((response) => response.json())
.then(function (data) {
// setup the fake server with entire dataset
const fakeServer = new FakeServer(data);
// create datasource with a reference to the fake server
const datasource = getServerSideDatasource(fakeServer);
// register the datasource with the grid
gridApi!.setGridOption("serverSideDatasource", datasource);
});
if (typeof window !== "undefined") {
// Attach external event handlers to window so they can be called from index.html
(<any>window).onBtRetry = onBtRetry;
(<any>window).onBtReset = onBtReset;
}
.example-wrapper {
display: flex;
flex-direction: column;
height: 100%;
}
#myGrid {
flex: 1 1 auto;
width: 100%;
}
// This fake server uses http://alasql.org/ to mimic how a real server
// might generate sql queries from the Server-Side Row Model request.
// To keep things simple it does the bare minimum to support the example.
export function FakeServer(allData) {
alasql.options.cache = false;
return {
getData: function (request) {
const failLoad = document.querySelector('#failLoad').checked === true;
if (failLoad) {
return {
success: false,
};
}
const results = executeQuery(request);
return {
success: true,
rows: results,
lastRow: getLastRowIndex(request),
};
},
};
function executeQuery(request) {
const sql = buildSql(request);
console.log('[FakeServer] - about to execute query:', sql);
return alasql(sql, [allData]);
}
function buildSql(request) {
return (
selectSql(request) +
' FROM ?' +
whereSql(request) +
groupBySql(request) +
orderBySql(request) +
limitSql(request)
);
}
function selectSql(request) {
const rowGroupCols = request.rowGroupCols;
const valueCols = request.valueCols;
const groupKeys = request.groupKeys;
if (isDoingGrouping(rowGroupCols, groupKeys)) {
const rowGroupCol = rowGroupCols[groupKeys.length];
const colsToSelect = [rowGroupCol.id];
valueCols.forEach(function (valueCol) {
colsToSelect.push(valueCol.aggFunc + '(' + valueCol.id + ') AS ' + valueCol.id);
});
return 'SELECT ' + colsToSelect.join(', ');
}
return 'SELECT *';
}
function whereSql(request) {
const rowGroups = request.rowGroupCols;
const groupKeys = request.groupKeys;
const whereParts = [];
if (groupKeys) {
groupKeys.forEach(function (key, i) {
const value = typeof key === 'string' ? "'" + key + "'" : key;
whereParts.push(rowGroups[i].id + ' = ' + value);
});
}
if (whereParts.length > 0) {
return ' WHERE ' + whereParts.join(' AND ');
}
return '';
}
function groupBySql(request) {
const rowGroupCols = request.rowGroupCols;
const groupKeys = request.groupKeys;
if (isDoingGrouping(rowGroupCols, groupKeys)) {
const rowGroupCol = rowGroupCols[groupKeys.length];
return ' GROUP BY ' + rowGroupCol.id + ' HAVING count(*) > 0';
}
return '';
}
function orderBySql(request) {
const sortModel = request.sortModel;
if (sortModel.length === 0) return '';
const sorts = sortModel.map(function (s) {
return s.colId + ' ' + s.sort.toUpperCase();
});
return ' ORDER BY ' + sorts.join(', ');
}
function limitSql(request) {
if (request.endRow == undefined || request.startRow == undefined) {
return '';
}
const blockSize = request.endRow - request.startRow;
return ' LIMIT ' + blockSize + ' OFFSET ' + request.startRow;
}
function isDoingGrouping(rowGroupCols, groupKeys) {
// we are not doing grouping if at the lowest level
return rowGroupCols.length > groupKeys.length;
}
function getLastRowIndex(request) {
return executeQuery({ ...request, startRow: undefined, endRow: undefined }).length;
}
}
<div class="example-wrapper">
<div style="margin-bottom: 5px">
<label><input type="checkbox" id="failLoad" /> Make Loads Fail</label>
<button onClick="onBtRetry()">Retry Failed Loads</button>
<button onClick="onBtReset()">Reset Entire Grid</button>
</div>
<div id="myGrid"></div>
</div>
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
}