JavaScript Data GridSaving Values

After editing a cell, the grid normally inserts the new value into your data using the column definition field attribute. This covers the most common case, where the grid owns the data state and treats the data as mutable.

This page discusses alternatives to this approach.

Value Setters provides an alternative to using field for setting the data. Use valueSetter if you want the grid to manage the data (ie update the data inline) but you want to update in a way other than using field. This is useful if you are not using field, or somehow need to manipulate the data in another way (e.g. the data item isn't a simple key / value pair map, but contains a more complex structure).

Read Only Edit stops the grid from updating data, and relies on the application to make the update after the edit is complete. Use this if you want to manage the grid data state externally, such as in a Redux store.

Value Setter

A Value Setter is the inverse of a Value Getter. Where the value getter allows getting values from your data using a function rather than a field, the value setter allows you to set values into your data using a function rather than specifying a field.

const gridOptions = {
    columnDefs: [
         // Option 1: using field for getting and setting the value
         { field: 'name' },
         // Options 2: using valueGetter and valueSetter - value getter used to get data
             valueGetter: params => {
             valueSetter: params => {
        = params.newValue;
                 return true;

    // other grid options ...

A value setter should return true if the value was updated successfully and false if the value was not updated (including if the value was not changed). When you return true, the grid knows it must refresh the cell.

string | ValueSetterFunc
Function or expression. Custom function to modify your data based off the new value for saving. Return true if the data changed.
valueSetter: string | ValueSetterFunc<TData>;

interface ValueSetterFunc<TData = any> {
    (params: ValueSetterParams<TData>) : boolean

interface ValueSetterParams<TData = any> {
  // The value before the change 
  oldValue: any;
  // The value after the change 
  newValue: any;
  // Row node for the given row 
  node: IRowNode<TData> | null;
  // Data associated with the node 
  data: TData;
  // Column for this callback 
  column: Column;
  // ColDef provided for this column 
  colDef: ColDef<TData>;
  // The grid api. 
  api: GridApi<TData>;
  // The column api. 
  columnApi: ColumnApi;
  // Application context as set on `gridOptions.context`. 
  context: any;

The example below demonstrates value setters working alongside value getters (value setters are typically only used alongside value getters). Note the following:

  • All columns are editable. After an edit, the example prints the updated row data to the console to show the impact of the edit.
  • Column Name uses valueGetter to combine the values from the two attributes firstName and lastName (separated by a space) and valueSetter is used to break the value up into the two same attributes.
  • Column A uses field for both getting and setting the value. This is the simple case for comparison.
  • Column B uses valueGetter and valueSetter instead of field for getting and setting the value. This allows the value to be parsed into the correct type before being saved.
  • Column C.X and C.Y use valueGetter to get the value from an embedded object. They then use valueSetter to set the value into the embedded object while also making sure the correct structure exists (this structure creation would not happen if using field).

Read Only Edit

Read Only Edit is a mode in the grid whereby Cell Editing will not update the data inside the grid. Instead the grid fires cellEditRequest events allowing the application to process the update request. To enable this mode, set the grid property readOnlyEdit=true.

Value has changed after editing. Only fires when readOnlyEdit=true.
onCellEditRequest = (
    event: CellEditRequestEvent<TData>
) => void;

interface CellEditRequestEvent<TData = any, TValue = any> {
  oldValue: any;
  newValue: any;
  source: string | undefined;
  column: Column;
  colDef: ColDef<TData>;
  // The value for the cell 
  value: TValue;
  // The user provided data for the row. 
  data: TData;
  // The row node. 
  node: IRowNode<TData>;
  // The visible row index for the row 
  rowIndex: number | null;
  // Either 'top', 'bottom' or null / undefined (if not set) 
  rowPinned: RowPinnedType;
  // If event was due to browser event (eg click), this is the browser event 
  event?: Event | null;
  // If the browser `event` is present the `eventPath` persists the `event.composedPath()` result for access within AG Grid event handlers.  
  eventPath?: EventTarget[];
  // The grid api. 
  api: GridApi<TData>;
  // The column api. 
  columnApi: ColumnApi;
  // Application context as set on `gridOptions.context`. 
  context: TContext;
  // Event identifier 
  type: string;

type RowPinnedType = 
    | 'bottom' 
    | null 
    | undefined
const gridOptions = {
   readOnlyEdit: true,
   onCellEditRequest: event => {
       console.log('Cell Editing updated a cell, but the grid did nothing!');
       // the application should update the data somehow

The example below has Cell Editing enabled, however the editing does nothing because readOnlyEdit=true is set. The application listens for cellEditRequest event and prints to the console. As the application does not try to update the data, the cell keeps its old value, giving the impression that editing is not working.

This next example extends the above by getting the application to update the data.

  1. The application listens for cellEditRequest and updates the Row Data.
  2. The Row Data has ID's and getRowId is implemented. This allows the grid to only refresh the desired row after new Row Data is set.

This final example is similar to before, except it uses Transactions to update the data after the edit rather than updating the whole Row Data.