This section covers saving and restoring the grid state, such as the filter model, selected rows, etc.
Saving and Restoring State Copy Link
The following buttons log saving and restoring state to the developer console.
import {
GridApi,
GridOptions,
GridPreDestroyedEvent,
ModuleRegistry,
StateUpdatedEvent,
createGrid,
enableDevValidations,
} from "ag-grid-community";
import { AllEnterpriseModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
ModuleRegistry.registerModules([AllEnterpriseModule]);
let gridApi: GridApi<IOlympicData>;
const gridOptions: GridOptions<IOlympicData> = {
gridId: "gridState",
columnDefs: [
{
field: "athlete",
minWidth: 150,
},
{ field: "age" },
{ field: "country", minWidth: 150 },
{
headerName: "Competition",
groupId: "competition",
children: [
{ field: "year" },
{ field: "date", minWidth: 150 },
{ field: "sport", minWidth: 150 },
],
},
{
headerName: "Medals",
groupId: "medals",
children: [
{ field: "gold" },
{ field: "silver", columnGroupShow: "open" },
{ field: "bronze", columnGroupShow: "open" },
{ field: "total", columnGroupShow: "closed" },
],
},
],
defaultColDef: {
flex: 1,
minWidth: 100,
filter: true,
enableRowGroup: true,
enablePivot: true,
enableValue: true,
headerNameEditable: true,
},
defaultColGroupDef: {
headerNameEditable: true,
},
autoGroupColumnDef: {
minWidth: 200,
},
sideBar: true,
toolbar: {
items: ["agQuickFilterToolbarItem", "agFindToolbarItem"],
},
pagination: true,
rowSelection: { mode: "multiRow" },
cellSelection: true,
calculatedColumns: true,
enableRowPinning: true,
suppressColumnMoveAnimation: true,
ensureDomOrder: true,
onGridPreDestroyed: onGridPreDestroyed,
onStateUpdated: onStateUpdated,
};
function onGridPreDestroyed(event: GridPreDestroyedEvent<IOlympicData>): void {
console.log("Grid state on destroy (can be persisted)", event.state);
}
function onStateUpdated(event: StateUpdatedEvent<IOlympicData>): void {
console.log("State updated", event.state);
}
function reloadGrid() {
const state = gridApi.getState();
gridApi.destroy();
const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridOptions.initialState = state;
gridApi = createGrid(gridDiv, gridOptions);
fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
.then((response) => response.json())
.then((data) => gridApi.setGridOption("rowData", data));
}
function printState() {
console.log("Grid state", gridApi.getState());
}
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((data: IOlympicData[]) => gridApi!.setGridOption("rowData", data));
if (typeof window !== "undefined") {
// Attach external event handlers to window so they can be called from index.html
(<any>window).reloadGrid = reloadGrid;
(<any>window).printState = printState;
}
.example-wrapper {
display: flex;
flex-direction: column;
height: 100%;
}
#myGrid {
flex: 1 1 0px;
width: 100%;
}
.button-group {
padding-bottom: 4px;
display: inline-block;
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 13px;
}
.button-group > * {
margin-right: 4px;
}
<div class="example-wrapper">
<div>
<span class="button-group">
<button onclick="reloadGrid()">Recreate Grid with Current State</button>
<button onclick="printState()">Print State</button>
</span>
</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
} The initial state is provided via the grid option initialState. It is only read once when the grid is created.
const gridOptions = {
initialState: {
filter: {
filterModel: {
year: {
filterType: 'set',
values: ['2012'],
}
}
},
columnVisibility: {
hiddenColIds: ['athlete'],
},
rowGroup: {
groupColIds: ['athlete'],
}
},
// other grid options ...
}The current grid state can be retrieved by listening to the state updated event, which is fired with the latest state when it changes, or via api.getState().
The state is also passed in the Grid Pre-Destroyed Event, which can be used to get the state when the grid is destroyed.
Invoked immediately before the grid is destroyed. This is useful for cleanup logic that needs to run before the grid is torn down. |
Grid state has been updated. |
State Contents Copy Link
The grid state is made up of the sections below, each of which can be provided or omitted independently. If applying some but not all of the column state properties, then initialState.partialColumnState must be set to true.
partialColumnState controls which column state sections you supply, not whether those sections may themselves be partial. Any section you include must match its documented shape.
The state also contains the grid version number. When applying state with older version numbers, any old state properties will be automatically migrated to the current format.
The grid state is designed to be serialisable, so any functions will be stripped out. For example, aggregation functions should be Registered as Custom Functions to work with state rather than being set as Directly Applied Functions.
Properties available on the GridState interface.
Grid version number |
Aggregation Functions (column state) |
Opened Column Groups, and column group header names edited by end users |
Column Order (column state) |
Left/right Pinned Columns (column state) |
Column Sizes - width/flex (column state) |
Hidden Columns (column state) |
Column Header Names edited by end users (column state) |
Column Filters and Advanced Filter |
Find search value and active match. Works for Client-Side Row Model only, and only when the Quick Access Toolbar is configured with agFindToolbarItem; otherwise the findSearchValue grid option is the only source
|
Quick Filter search text. Only captured and restored when the Quick Access Toolbar is configured with agQuickFilterToolbarItem; otherwise the quickFilterText grid option is the only source
|
Currently focused cell. Works for Client-Side Row Model only |
Current page |
Currently manually pinned rows |
Current pivot mode and pivot columns, and pivot column label sort (column state) |
Currently selected cell ranges |
Current Row Group Columns (column state) |
Currently expanded group rows |
Currently expanded Server-Side Row Model group rows when using ssrmExpandAllAffectsAllRows |
Currently selected rows. For Server-Side Row Model, will be ServerSideRowSelectionState | ServerSideRowGroupSelectionState, for other row models, will be an array of row IDs. Can only be set for Client-Side Row Model and Server-Side Row Model.
|
Current scroll position. Works for Client-Side Row Model only |
Current Side Bar positioning and opened tool panel, including the state of each open tool panel |
Current sort columns and direction (column state) |
The per-column "Show Values As" mode (column state) |
Columns the user created or removed at runtime, such as Calculated Columns, along with the column definition properties they changed. Unlike the other sections, which configure existing columns, this section can create and remove them.
|
When providing a partial initialState with some but not all column state properties, set this to true. This controls which top-level sections are supplied, not whether a section may itself be partial: any section you provide must match its documented shape. Not required if passing the whole state object retrieved from the grid. Not used for api.setState(), as that instead takes a second argument of properties to ignore.
|
When restoring the current page using the Server Side Row Model or Infinite Row Model, additional configuration is required:
- For the Server Side Row Model - set the
serverSideInitialRowCountproperty to a value which includes the rows to be shown. - For the Infinite Row Model - set the
infiniteInitialRowCountproperty to a value which includes the rows to be shown.
Column and Group IDs Copy Link
Give every column a colId or a field, and every column group a groupId. Without them, state can be restored onto the wrong column.
Columns are identified in the state by their Column ID, and Column Groups by their groupId. These IDs are the only link between a saved state and the columns it describes, so they need to mean the same thing when the state is restored as they did when it was saved.
A column that provides neither colId nor field - one using only a valueGetter, for example - is given a positional ID instead. That ID follows the column's position in columnDefs rather than the column itself. If the definitions are reordered between saving and restoring, each column's state is applied to whichever column now occupies its old position.
This affects every column state section: sizes, sort, pinning, visibility, order and header names. A restored grid can silently show another column's width, or a header the user renamed on the wrong column.
Column groups behave the same way. A group definition without a groupId is given a generated ID which changes when the column definitions change, so the open / closed state of that group may not be restored.
Setting State Copy Link
The best way to restore grid state is via initial state as described above. However, it is also possible to restore state on an existing grid via api.setState(state).
setState should only be used to restore grid state. The grid does not support being used as a controlled component, so do not call this on every state update.
It is possible to maintain the existing state for individual state contents by passing a second argument to setState that contains the top-level properties to ignore. E.g. api.setState(state, ['filter']) will maintain the existing filter state in the grid.
Anything the provided state omits is reset rather than left as is. For example, a state without a quickFilter section clears the quick filter value in the toolbar.
import {
GridApi,
GridOptions,
GridPreDestroyedEvent,
GridState,
ModuleRegistry,
StateUpdatedEvent,
createGrid,
enableDevValidations,
} from "ag-grid-community";
import { AllEnterpriseModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
ModuleRegistry.registerModules([AllEnterpriseModule]);
let gridApi: GridApi<IOlympicData>;
const gridOptions: GridOptions<IOlympicData> = {
gridId: "setState",
columnDefs: [
{
field: "athlete",
minWidth: 150,
},
{ field: "age" },
{ field: "country", minWidth: 150 },
{
headerName: "Competition",
groupId: "competition",
children: [
{ field: "year" },
{ field: "date", minWidth: 150 },
{ field: "sport", minWidth: 150 },
],
},
{
headerName: "Medals",
groupId: "medals",
children: [
{ field: "gold" },
{ field: "silver", columnGroupShow: "open" },
{ field: "bronze", columnGroupShow: "open" },
{ field: "total", columnGroupShow: "closed" },
],
},
],
defaultColDef: {
flex: 1,
minWidth: 100,
filter: true,
enableRowGroup: true,
enablePivot: true,
enableValue: true,
headerNameEditable: true,
},
defaultColGroupDef: {
headerNameEditable: true,
},
autoGroupColumnDef: {
minWidth: 200,
},
sideBar: true,
toolbar: {
items: ["agQuickFilterToolbarItem", "agFindToolbarItem"],
},
pagination: true,
rowSelection: { mode: "multiRow" },
cellSelection: true,
calculatedColumns: true,
enableRowPinning: true,
suppressColumnMoveAnimation: true,
onGridPreDestroyed: onGridPreDestroyed,
onStateUpdated: onStateUpdated,
};
function onGridPreDestroyed(event: GridPreDestroyedEvent<IOlympicData>): void {
console.log("Grid state on destroy (can be persisted)", event.state);
}
function onStateUpdated(event: StateUpdatedEvent<IOlympicData>): void {
console.log("State updated", event.state);
}
function reloadGrid() {
gridApi.destroy();
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((data) => gridApi.setGridOption("rowData", data));
}
function printState() {
console.log("Grid state", gridApi.getState());
}
let savedState: GridState | undefined;
function saveState() {
savedState = gridApi.getState();
console.log("Saved state", savedState);
}
function setState() {
if (savedState) {
gridApi.setState(savedState);
console.log("Set state", savedState);
}
}
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((data: IOlympicData[]) => gridApi!.setGridOption("rowData", data));
if (typeof window !== "undefined") {
// Attach external event handlers to window so they can be called from index.html
(<any>window).reloadGrid = reloadGrid;
(<any>window).printState = printState;
(<any>window).saveState = saveState;
(<any>window).setState = setState;
}
.example-wrapper {
display: flex;
flex-direction: column;
height: 100%;
}
#myGrid {
flex: 1 1 0px;
width: 100%;
}
.button-group {
padding-bottom: 4px;
display: inline-block;
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 13px;
}
.button-group > * {
margin-right: 4px;
}
<div class="example-wrapper">
<div>
<span class="button-group">
<button onclick="saveState()">Save State</button>
<button onclick="reloadGrid()">Recreate Grid with No State</button>
<button onclick="setState()">Set State</button>
<button onclick="printState()">Print State</button>
</span>
</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
} Converting Column State to Grid State Copy Link
State retrieved via the Column State APIs can be converted into grid state via the helper functions convertColumnState and convertColumnGroupState.
const state = {
...convertColumnState(columnState),
...convertColumnGroupState(columnGroupState)
};