ag-Grid gives great flexibility in saving and restoring its state. This is especially useful when your users want to have their own ag-Grid configuration by default, or switch between different views and keep the ag-Grid setup when they return. You can also save ag-Grid state as part of the user profile and load it each time a user opens the application. In this post we will show how to do this by persisting ag-Grid state using React and Redux.

We've demonstrated this in an example with several views, each having a few tabs. Each of these tabs hosts an instance of ag-Grid with its own state that gets persisted as the user makes changes to the application.

Please see a GIF illustrating this below and note how the configuration (state) of ag-Grid is saved and then restored after the page is refreshed:

Please try this out the live sample below following these steps:

  1. On the active tab, change the state of ag-Grid. For example, hide columns from the columns menu on the right by unchecking some of the checkboxes.
    You can also filter by hovering over a column header and selecting the filter menu.
  2. Now switch between views or tabs and note that when you come back to the original tab, the ag-Grid state is exactly as you left it in step (1).
  3. You can also save your changes to Local Storage by clicking SAVE STATE TO LOCAL STORAGE button.
  4. Now you can refresh the page and note you'll have the same ag-Grid state loaded after the refresh.
Note: The ag-Grid state gets stored to Redux store whenever the user performs an action. However, when you refresh the page the Redux state is lost. This is why we added the SAVE STATE TO LOCAL STORAGE button to save the Redux store to LocalStorage. This way when you reload the page the application initilizes the store from LocalStorage and restores the ag-Grid state.



Managing state in ag-Grid

So how is this implemented? ag-Grid provides granular control over which aspects of its state you wish to get or set through its API. In our project we are going to save filter, sort, column, column group and pivot enabled/disabled state. We will use ag-Grid state change events for saving the state and the onFirstDataRendered event to restore the saved state whenever the user refreshes the page or switches between tabs.

onFirstDataRendered is an event that gets triggered when the grid is initialized and the data has been rendered in the grid. We use it to restore any persisted state on ag-Grid.

The approach to save and restore state is almost identical for the different aspects of ag-Grid, so please jump to the part you are interested in:

Column Sort state

You can save and restore the sorting state of columns in ag-Grid, as shown by the GIF below:

Here are the steps for saving and restoring column sort state implemented in code below.

  1. When the columns get sorted a sortChanged event will get fired.
  2. We add an onSortChanged event listener to <AgGridReact/> Component.
  3. In our listener we save the Column sort state by calling the api.getSortModel() and we dispatch an action with the sort state as its payload.
  4. The reducer saves the sort state to our Redux store.
  5. Finally we add onFirstDataRendered listener to restore the state from our Redux store.
// [...]
// src/components/MyGrid/MyGrid.jsx

class MyGrid extends Component {
  // [...]

  onSortChanged(params) {
    let sortModel = params.api.getSortModel();
    this.props.actions.saveGridSortModel(this.props.id, sortModel);
  }

  onFirstDataRendered(params) {
    //	[...]
    let sortModel = this.props?.sortModel;
    if (sortModel) {
      this.gridApi.setSortModel(sortModel);
    }
  }

  render() {
    // [...]
    return (
      <AgGridReact
        onSortChanged={this.onSortChanged.bind(this)}
        onFilterChanged={this.onFilterChanged.bind(this)}
      />
    );
  }
}

You can learn more about sorting in ag-Grid here - Row Sorting, Sorting API.

Column Filter state

You can save and later restore the filter applied to a column in ag-Grid, as shown by the GIF below:

Here are the steps for saving and restoring filter state implemented in code below.

  1. When the columns get filtered a filterChanged event will get fired.
  2. We add an onFilterChanged event listener to <AgGridReact /> Component.
  3. In our listener we save the filter state by calling the api.getFilterModel() and we dispatch an action with the filter state as its payload
  4. The reducer saves the filter state to our Redux store.
  5. Finally we add onFirstDataRendered listener that simply restores the state from our Redux store.
// [...]
// src/components/MyGrid/MyGrid.jsx

class MyGrid extends Component {
  // [...]

  onFilterChanged(params) {
    let filterModel = params.api.getFilterModel();
    this.props.actions.saveGridFilterModel(this.props.id, filterModel);
  }

  onFirstDataRendered(params) {
    //	[...]
    let filterModel = this.props?.filterModel;

    if (filterModel) {
      this.gridApi.setFilterModel(filterModel);
    }
  }

  render() {
    // [...]
    return (
      <AgGridReact
        onFirstDataRendered={this.onFirstDataRendered.bind(this)}
        onFilterChanged={this.onFilterChanged.bind(this)}
      />
    );
  }
}

You can learn more about filtering in ag-Grid here - Column Filters, Filter API.

Column & Column Group state

You can save and restore ag-Grid state including pinned columns, column size, visibility and order. Please see these illustrated in GIF below:

Here are the steps for saving and restoring Column & Column Group state implemented in code below.

  1. When the user resizes, pins, moves columns and hides columns the grid will fire the following events: columnResized, columnPinned ,columnMoved ,columnVisible, columnValueChanged, columnPivotChanged.  
  2. We add the same listener for all the above events on the <AgGridReact /> Component.
  3. In our listener we save the column & column group state by calling the gridColumnApi.getColumnState() & gridColumnApi.getColumnGroupState() and  we dispatch 2 actions, one for saving column state and the other for column group state, both of them will send the corresponding state as the payload
  4. The reducer saves the column & column group state to our Redux store.
  5. Finally we add onFirstDataRendered listener that simply restores the state from our redux store.
// [...]
// src/components/MyGrid/MyGrid.jsx

class MyGrid extends Component {
  // [...]

  onSaveGridColumnState(e) {
    if (!this.gridColumnApi) return;
    let columnState = this.gridColumnApi?.getColumnState();
    let columnGroupState = this.gridColumnApi?.getColumnGroupState();

    this.debounceSaveGridColumnState(this.props.id, columnState);
    this.debounceSaveGridColumnGroupState(this.props.id, columnGroupState);
  }

  onFirstDataRendered(params) {
    //	[...]
    let columnState = this.props?.columnState;
    let columnGroupState = this.props?.columnGroupState;

    if (columnState) {
      this.gridColumnApi.setColumnState(columnState);
    }

    if (columnGroupState) {
      this.gridColumnApi.setColumnGroupState(columnGroupState);
    }
  }

  render() {
    // [...]
    return (
      <AgGridReact
        onFirstDataRendered={this.onFirstDataRendered.bind(this)}
        onColumnVisible={this.onSaveGridColumnState.bind(this)}
        onColumnPinned={this.onSaveGridColumnState.bind(this)}
        onColumnResized={this.onSaveGridColumnState.bind(this)}
        onColumnMoved={this.onSaveGridColumnState.bind(this)}
        onColumnRowGroupChanged={this.onSaveGridColumnState.bind(this)}
        onColumnValueChanged={this.onSaveGridColumnState.bind(this)} // A value column was added or removed.
        onColumnPivotChanged={this.onSaveGridColumnState.bind(this)} // A pivot column was added, removed or order changed.
      />
    );
  }
}

You can learn more about column and column groups in ag-Grid here - Column Groups, Saving and Restoring Column State.

Pivot mode enabled / disabled state

You can save and restore the pivot mode state in ag-Grid, as shown by the GIF below:

Here are the steps for saving and restoring pivot on/off state implemented in the code below.

  1. When the Pivot Mode is toggled a columnPivotModeChanged event gets fired.
  2. We add an onColumnPivotModeChanged event listener to <AgGridReact /> Component.
  3. In our listener we save the pivot mode state by calling the gridColumnApi.isPivotMode() and we dispatch an action with the pivot state as its payload
  4. The reducer saves the pivot state to our Redux store.
  5. Finally, we add onFirstDataRendered listener that simply restores the state from our Redux store.
// [...]
// src/components/MyGrid/MyGrid.jsx

class MyGrid extends Component {
  // [...]

  onSavePivotModeState() {
    let isPivotMode = this.gridColumnApi.isPivotMode();

    let isPivotModeDifferentFromProps =
      this.gridColumnApi.isPivotMode() !== this.props.isPivotMode;
    if (isPivotModeDifferentFromProps)
      this.debounceSaveGridPivotModeState(this.props.id, isPivotMode);
  }

  onFirstDataRendered(params) {
    //	[...]

    let isPivotMode = this.props?.isPivotMode; // boolean
    let isPivotModeDifferent =
      this.gridColumnApi?.isPivotMode() !== this?.props?.isPivotMode;

    if (this?.props?.isPivotMode !== undefined && isPivotModeDifferent) {
      this.gridColumnApi.setPivotMode(isPivotMode);
    }
  }

  render() {
    // [...]
    return (
      <AgGridReact
        onFirstDataRendered={this.onFirstDataRendered.bind(this)}
        onColumnPivotModeChanged={this.onSavePivotModeState.bind(this)}
      />
    );
  }
}

You can learn more about pivoting in ag-Grid here - Pivoting, Saving & Restoring Column State with Pivot.

What's next?

I hope you find this article useful when persisting state with ag-Grid. Please check out our other blog posts and documentation for a great variety of scenarios you can implement with ag-Grid.

If you would like to try out ag-Grid check out our getting started guides (JS / React / Angular / Vue)

Happy coding!