React Data GridCell Editors
react logo

Create your own cell editor by providing a cell editor component.

The example below shows a few cell editors in action.

  • The Doubling Cell Editor will double a given input and reject values over a 1000
  • The Mood Cell Editor illustrates a slightly more complicated editor with values changed depending on the smiley chosen
  • The Numeric Cell Editor illustrates a slightly more complicated numeric editor to the Doubling editor, with increased input validation

Implementing a Cell Editor Component

To configure custom cell editors, first enable the grid option reactiveCustomComponents.

Custom cell editors components are controlled components, which receive a value as part of the props, and pass value updates back to the grid via the onValueChange callback. Note that the value is not set until editing stops.

export default ({ value, onValueChange }) => {
    return (
        <input
            type="text"
            value={value || ''}
            onChange={({ target: { value }}) => onValueChange(value === '' ? null : value)}
        />
    );
}

Enabling reactiveCustomComponents affects all custom components. If you have custom components built in an imperative way instead of setting the reactiveCustomComponents option, they may need to be rebuilt to take advantage of the new features that reactiveCustomComponents offers. Using custom components built in an imperative way is now deprecated, and in AG Grid v32 the reactiveCustomComponents option will be true by default. See Migrating to Use reactiveCustomComponents. For the legacy imperative documentation, see Imperative Cell Editor Component.

Custom Cell Editor Parameters

Cell Editor Props

The following props are passed to the custom cell editor components (CustomCellEditorProps interface). If custom props are provided via the colDef.cellEditorParams property, these will be additionally added to the props object, overriding items of the same name if a name clash exists.

Cell Editor Callbacks

The following callbacks can be passed to the useGridCellEditor hook (CustomCellEditorCallbacks interface). All the callbacks are optional, and the hook only needs to be used if callbacks are provided.

Registering Cell Editors with Columns

See the section registering custom components for details on registering and using custom cell editors.

Complementing Cell Editor Params

As with cell renderers, cell editors can also be provided with additional parameters. Do this using cellEditorParams as in the following example which will pass 'Ireland' as the 'country' parameter:

colDef = {
    cellEditor: MyCellEditor,    
    cellEditorParams: {
        // make "country" value available to cell editor
        country: 'Ireland'
    },
    // ...other props
}

Configure Popup

Configure that an Editor is in a popup by setting cellEditorPopup=true on the Column Definition.

colDef = {
    cellEditorPopup: true,
    // ...other props
}

Configure Popup Position

By default Popup Editors appear over the editing Cell. It is also possible to have the Cell Editor appear below the Cell, so the user can see the Cell contents while editing.

Configure the Popup Editor to appear below the Cell by setting cellEditorPopupPosition='under' on the Column Definition.

colDef = {
    cellEditorPopupPosition: 'under',
    // ...other props
}

Keyboard Navigation While Editing

If you provide a cell editor, you may wish to disable some of the grids keyboard navigation. For example, if you are providing a simple text editor, you may wish the grid to do nothing when you press the right and left arrows (the default is the grid will move to the next / previous cell) as you may want the right and left arrows to move the cursor inside your editor. In other cell editors, you may wish the grid to behave as normal.

Because different cell editors will have different requirements on what the grid does, it is up to the cell editor to decide which event it wants the grid to handle and which it does not.

You have two options to stop the grid from doing it's default action on certain key events:

  1. Stop propagation of the event to the grid in the cell editor.
  2. Tell the grid to do nothing via the colDef.suppressKeyEvent() callback.

Option 1 - Stop Propagation

If you don't want the grid to act on an event, call event.stopPropagation(). The advantage of this method is that your cell editor takes care of everything, good for creating reusable cell editors.

The follow code snippet is one you could include for a simple text editor, which would stop the grid from doing navigation.

const KEY_LEFT = 'ArrowLeft';
const KEY_UP = 'ArrowUp';
const KEY_RIGHT = 'ArrowRight';
const KEY_DOWN = 'ArrowDown';
const KEY_PAGE_UP = 'PageUp';
const KEY_PAGE_DOWN = 'PageDown';
const KEY_PAGE_HOME = 'Home';
const KEY_PAGE_END = 'End';

const MyCellEditor = ({ value, onValueChange }) => {
    const onKeyDown = (event) => {
        const key = { event };

        const isNavigationKey = key === KEY_LEFT ||
            key === KEY_RIGHT ||
            key === KEY_UP ||
            key === KEY_DOWN ||
            key === KEY_PAGE_DOWN ||
            key === KEY_PAGE_UP ||
            key === KEY_PAGE_HOME ||
            key === KEY_PAGE_END;

        if (isNavigationKey) {
            // this stops the grid from receiving the event and executing keyboard navigation
            event.stopPropagation();
        }
    }

    return (
        <input
            value={value || ''}
            onChange={({ target: { value: newValue }) => onValueChange(newValue)}
            onKeyDownCapture={onKeyDown}
        />
    );
});

Option 2 - Suppress Keyboard Event

If you implement colDef.suppressKeyboardEvent(), you can tell the grid which events you want process and which not. The advantage of this method of the previous method is it takes the responsibility out of the cell editor and into the column definition. So if you are using a reusable, or third party, cell editor, and the editor doesn't have this logic in it, you can add the logic via configuration.

const KEY_UP = 'ArrowUp';
const KEY_DOWN = 'ArrowDown';

const GridExample = () => {
    // rest of the component

    const columnDefs = [
        {
            field: 'value',
            suppressKeyboardEvent={params => {
                console.log('cell is editing: ' + params.editing);
                console.log('keyboard event:', params.event);

                // return true (to suppress) if editing and user hit up/down keys
                const key = params.event.key;
                const gridShouldDoNothing = params.editing && (key === KEY_UP || key === KEY_DOWN);
                return gridShouldDoNothing;
            }
        }
    ];

    return (
        <div
            style={{
                height: '100%',
                width: '100%'
            }}
            className="ag-theme-quartz test-grid">
            <AgGridReact ...rest of the definition...>
                columnDefs={columnDefs}
                />
            </AgGridReact>
        </div>
    );
};

Cell Editing Example

The example below illustrates:

  • 'Gender' column uses a Component cell editor that allows choices via a 'richSelect' (AG Grid Enterprise only), with values supplied by complementing the editor parameters.
  • 'Age' column uses a Component cell editor that allows simple integer input only.
  • 'Mood' column uses a custom Component cell editor and renderer that allows choice of mood based on image selection.
  • 'Address' column uses a Component cell editor that allows input of multiline text via a 'largeText'. ⇥ Tab and ⎋ Esc (amongst others) will exit editing in this field, ⇧ Shift+↵ Enter will allow newlines.
  • 'Country' columns shows using 'richSelect' for a complex object - the cell renderer takes care of only rendering the country name.

Accessing Cell Editor Instances

After the grid has created an instance of a cell editor for a cell it is possible to access that instance. This is useful if you want to call a method that you provide on the cell editor that has nothing to do with the operation of the grid. Accessing cell editors is done using the grid API getCellEditorInstances(params).

If you are doing normal editing, then only one cell is editable at any given time. For this reason if you call getCellEditorInstances() with no params, it will return back the editing cell's editor if a cell is editing, or an empty list if no cell is editing.

The instances returned by the grid will be wrapper components that match the provided grid cell editor components that implement ICellEditor. To get the React custom cell editor component, the helper function getInstance can be used with this.

An example of calling getCellEditorInstances() is as follows:

const instances = api.getCellEditorInstances(params);
if (instances.length > 0) {
    getInstance(instances[0], instance => {
        ...
    });
}

The example below shows using getCellEditorInstances. The following can be noted:

  • All cells are editable.
  • First Name and Last Name use the default editor.
  • All other columns use the provided MySimpleCellEditor editor.
  • The example sets an interval to print information from the active cell editor. There are three results: 1) No editing 2) Editing with default cell renderer and 3) editing with the custom cell editor. All results are printed to the developer console.