---
title: "Edit Components"
framework: javascript
version: "36.1.0"
---

# Edit Components

A Cell Editor Component is the UI that appears, normally inside the Cell, that takes care of the Edit operation. You can select from the [Provided Cell Editors](https://www.ag-grid.com/javascript-data-grid/provided-cell-editors/) or create your own Custom Cell Editor Components.

The example below shows some Provided Editor Components and some Custom Editor Components.

#### Simple Editor Components

```ts
import {
  ClientSideRowModelModule,
  ColDef,
  CustomEditorModule,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberEditorModule,
  TextEditorModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import { RichSelectModule } from "ag-grid-enterprise";
import { getData } from "./data";
import { GenderRenderer } from "./genderRenderer";
import { MoodEditor } from "./moodEditor";
import { MoodRenderer } from "./moodRenderer";
import { SimpleTextEditor } from "./simpleTextEditor";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  RichSelectModule,
  NumberEditorModule,
  TextEditorModule,
  CustomEditorModule,
]);

const columnDefs: ColDef[] = [
  { field: "first_name", headerName: "Provided Text" },
  {
    field: "last_name",
    headerName: "Custom Text",
    cellEditor: SimpleTextEditor,
  },
  {
    field: "age",
    headerName: "Provided Number",
    cellEditor: "agNumberCellEditor",
  },
  {
    field: "gender",
    headerName: "Provided Rich Select",
    cellRenderer: GenderRenderer,
    cellEditor: "agRichSelectCellEditor",
    cellEditorParams: {
      cellRenderer: GenderRenderer,
      values: ["Male", "Female"],
    },
  },
  {
    field: "mood",
    headerName: "Custom Mood",
    cellRenderer: MoodRenderer,
    cellEditor: MoodEditor,
    cellEditorPopup: true,
  },
];

let gridApi: GridApi;

const gridOptions: GridOptions = {
  columnDefs: columnDefs,
  rowData: getData(),
  defaultColDef: {
    editable: true,
    flex: 1,
    minWidth: 100,
  },
};

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);
```

[Live example: Simple Editor Components](https://www.ag-grid.com/examples/cell-editors/component-editor-2/typescript)

## Custom Components

To create a custom cell editor, implement the `ICellEditorComp` interface, which defines two mandatory methods:

- `getGui()` - returns the DOM element of your editor for the grid to display
- `getValue()` - called by the grid to get the final value when editing is complete.

Full details of the `ICellEditorComp` and `ICellEditorParams` interfaces are listed below under [API Reference](#api-reference).

## Selecting Components

Cell Editor Components are configured using the `cellEditor` property of the [Column Definition](https://www.ag-grid.com/javascript-data-grid/column-definitions/).

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `cellEditor` | `any` |  |  | Provide your own cell editor component for this column's cells. |

```js
const gridOptions = {
    columnDefs: [
        {
            field: 'name',
            editable: true,
            // uses a provided editor, referenced by name
            cellEditor: 'agTextCellEditor'
        },
        {
            field: 'name',
            editable: true,
            // uses a custom editor, referenced directly
            cellEditor: 'CustomEditorComp'
        },
    ],

    // other grid options ...
}
```

See [Registering Custom Components](https://www.ag-grid.com/javascript-data-grid/components/#registering-custom-components) for details on how to register your custom grid components.

## Dynamic Selection

The `colDef.cellEditorSelector` function allows setting different Editor Components for different Rows within a Column.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `cellEditorSelector` | `CellEditorSelectorFunc` |  |  | Callback to select which cell editor to be used for a given row within the same column. |

The `params` passed to `cellEditorSelector` are the same as those passed to the Editor Component. Typically the selector will use this to check the row's contents and choose an editor accordingly.

The result is an object with `component` and `params` to use instead of `cellEditor` and `cellEditorParams`.

This following shows the Selector always returning back the provided Rich Select Editor:

```js
cellEditorSelector: params => {
    return {
        component: 'agRichSelectCellEditor',
        params: { values: ['Male', 'Female'] }
    };
}
```

However a selector only makes sense when a selection is made. The following demonstrates selecting between Cell Editors:

```js
cellEditorSelector: params => {

  if (params.data.type === 'age') {
    return {
      component: NumericCellEditor,
    }
  }

  if (params.data.type === 'gender') {
    return {
      component: 'agRichSelectCellEditor',
      params: {
        values: ['Male', 'Female']
      }
    }
  }

  if (params.data.type === 'mood') {
    return {
      component: MoodEditor,
      popup: true,
      popupPosition: 'under'
    }
  }

  return undefined
}
```

Here is a full example:

- The column 'Value' holds data of different types as shown in the column 'Type' (numbers/genders/moods).
- `colDef.cellEditorSelector` is a function that returns the name of the component to use to edit based on the type of data for that row
- Edit a cell by double clicking to observe the different editors used.

#### Dynamic Editor Component

```ts
import {
  CellEditingStartedEvent,
  CellEditingStoppedEvent,
  CellEditorSelectorResult,
  ClientSideRowModelModule,
  GridApi,
  GridOptions,
  ICellEditorParams,
  ModuleRegistry,
  NumberEditorModule,
  RowEditingStartedEvent,
  RowEditingStoppedEvent,
  TextEditorModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
  RichSelectModule,
} from "ag-grid-enterprise";
import { IRow, getData } from "./data";
import { MoodEditor } from "./moodEditor";
import { NumericCellEditor } from "./numericCellEditor";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  NumberEditorModule,
  TextEditorModule,
  ClientSideRowModelModule,
  ColumnsToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  RichSelectModule,
]);

let gridApi: GridApi<IRow>;

const gridOptions: GridOptions<IRow> = {
  columnDefs: [
    { field: "type" },
    {
      field: "value",
      editable: true,
      cellEditorSelector: cellEditorSelector,
    },
  ],
  defaultColDef: {
    flex: 1,
    cellDataType: false,
  },
  rowData: getData(),

  onRowEditingStarted: onRowEditingStarted,
  onRowEditingStopped: onRowEditingStopped,
  onCellEditingStarted: onCellEditingStarted,
  onCellEditingStopped: onCellEditingStopped,
};

function onRowEditingStarted(event: RowEditingStartedEvent) {
  console.log("never called - not doing row editing");
}

function onRowEditingStopped(event: RowEditingStoppedEvent) {
  console.log("never called - not doing row editing");
}

function onCellEditingStarted(event: CellEditingStartedEvent) {
  console.log("cellEditingStarted");
}

function onCellEditingStopped(event: CellEditingStoppedEvent) {
  console.log("cellEditingStopped");
}

function cellEditorSelector(
  params: ICellEditorParams<IRow>,
): CellEditorSelectorResult | undefined {
  if (params.data.type === "age") {
    return {
      component: NumericCellEditor,
    };
  }

  if (params.data.type === "gender") {
    return {
      component: "agRichSelectCellEditor",
      params: {
        values: ["Male", "Female"],
      },
    };
  }

  if (params.data.type === "mood") {
    return {
      component: MoodEditor,
      popup: true,
      popupPosition: "under",
    };
  }

  return undefined;
}

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);
```

[Live example: Dynamic Editor Component](https://www.ag-grid.com/examples/cell-editors/dynamic-editor-component/typescript)

## Custom Props

The property `colDef.cellEditorParams` allows custom props to be passed to editors.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `cellEditorParams` | `any` |  |  | Params to be passed to the `cellEditor` component. |

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

## Dynamic Props

The `colDef.cellEditorParams` function allows dynamic props independently of the Editor selection. For example you might have a 'City' column that has values based on the 'Country' column.

```js
cellEditorParams: params => {
    const selectedCountry = params.data.country;

    if (selectedCountry === 'Ireland') {
        return {
            values: ['Dublin', 'Cork', 'Galway']
        };
    } else {
        return {
            values: ['New York', 'Los Angeles', 'Chicago', 'Houston']
        };
    }
}
```

Below shows an example with dynamic props. The following can be noted:

- Column **Gender** uses a Cell Component for both the grid and the editor.
- Column **Country** allows country selection, with `cellHeight` being used to make each entry 50px tall. If the currently selected city for the row doesn't match a newly selected country, the city cell is cleared.
- Column **City** uses dynamic parameters to display values for the selected country, and uses `formatValue` to add the selected city's country as a suffix.
- Column **Address** uses the large text area editor.

#### Dynamic Parameters

```ts
import {
  CellValueChangedEvent,
  ClientSideRowModelModule,
  GridApi,
  GridOptions,
  ICellEditorParams,
  LargeTextEditorModule,
  ModuleRegistry,
  TextEditorModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
  RichSelectModule,
} from "ag-grid-enterprise";
import { IRow, getData } from "./data";
import { GenderCellRenderer } from "./genderCellRenderer";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  ColumnsToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  RichSelectModule,
  TextEditorModule,
  LargeTextEditorModule,
]);

const cellCellEditorParams = (params: ICellEditorParams<IRow>) => {
  const selectedCountry = params.data.country;
  const allowedCities = countyToCityMap(selectedCountry);

  return {
    values: allowedCities,
    formatValue: (value: any) => `${value} (${selectedCountry})`,
  };
};

let gridApi: GridApi;

const gridOptions: GridOptions = {
  columnDefs: [
    { field: "name" },
    {
      field: "gender",
      cellRenderer: GenderCellRenderer,
      cellEditor: "agRichSelectCellEditor",
      cellEditorParams: {
        values: ["Male", "Female"],
        cellRenderer: GenderCellRenderer,
      },
    },
    {
      field: "country",
      cellEditor: "agRichSelectCellEditor",
      cellEditorParams: {
        cellHeight: 50,
        values: ["Ireland", "USA"],
      },
    },
    {
      field: "city",
      cellEditor: "agRichSelectCellEditor",
      cellEditorParams: cellCellEditorParams,
    },
    {
      field: "address",
      cellEditor: "agLargeTextCellEditor",
      cellEditorPopup: true,
      minWidth: 550,
    },
  ],
  defaultColDef: {
    flex: 1,
    minWidth: 130,
    editable: true,
  },
  rowData: getData(),
  onCellValueChanged: onCellValueChanged,
};

function countyToCityMap(match: string): string[] {
  const map: { [key: string]: string[] } = {
    Ireland: ["Dublin", "Cork", "Galway"],
    USA: ["New York", "Los Angeles", "Chicago", "Houston"],
  };

  return map[match];
}

function onCellValueChanged(params: CellValueChangedEvent) {
  const colId = params.column.getId();

  if (colId === "country") {
    const selectedCountry = params.data.country;
    const selectedCity = params.data.city;
    const allowedCities = countyToCityMap(selectedCountry) || [];
    const cityMismatch = allowedCities.indexOf(selectedCity) < 0;

    if (cityMismatch) {
      params.node.setDataValue("city", null);
    }
  }
}

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);
```

[Live example: Dynamic Parameters](https://www.ag-grid.com/examples/cell-editors/dynamic-parameters/typescript)

## Popup Editor

An editor can be Inline or Popup.

An Inline Editor Component will be placed inside the Grid's Cell, replacing the Cell contents when active.

A Popup Editor Component appears in a popup over the Cell. Popup Editors are not constrained to the Cells dimensions.

Configure that a Custom Cell Editor is in a popup in one of the following ways:

1. Specify `cellEditorPopup=true` on the [Column Definition](https://www.ag-grid.com/javascript-data-grid/column-definitions/).
2. Implement the `isPopup()` method on the Custom Cell Editor and return `true`.

```js
colDefs = [
  {
    cellEditor: MyPopupEditor,
    cellEditorPopup: true
    // ...
  }
]
```

Popup Editors appear over the editing Cell. Configure the Popup Editor to appear below the Cell in one of the following ways:

1. Implement the `getPopupPosition()` method on the Custom Cell Editor and return `under`.
2. Specify `cellEditorPopupPosition='under'` on the [Column Definition](https://www.ag-grid.com/javascript-data-grid/column-definitions/).

```js
colDef = {
  cellEditorPopup: true,
  cellEditorPopupPosition: 'under',
  // ...other props
}
```

The following example demonstrates the same editor positioned inline, as a popup over the cell, and as a popup under the cell:

#### Popup Editor Components

```ts
import {
  ClientSideRowModelModule,
  ColDef,
  CustomEditorModule,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberEditorModule,
  TextEditorModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import { RichSelectModule } from "ag-grid-enterprise";
import { getData } from "./data";
import { MoodEditor } from "./moodEditor";
import { MoodRenderer } from "./moodRenderer";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  RichSelectModule,
  NumberEditorModule,
  TextEditorModule,
  CustomEditorModule,
]);

const columnDefs: ColDef[] = [
  {
    field: "mood",
    headerName: "Inline",
    cellRenderer: MoodRenderer,
    cellEditor: MoodEditor,
  },
  {
    field: "mood",
    headerName: "Popup Over",
    cellRenderer: MoodRenderer,
    cellEditor: MoodEditor,
    cellEditorPopup: true,
  },
  {
    field: "mood",
    headerName: "Popup Under",
    cellRenderer: MoodRenderer,
    cellEditor: MoodEditor,
    cellEditorPopup: true,
    cellEditorPopupPosition: "under",
  },
];

let gridApi: GridApi;

const gridOptions: GridOptions = {
  columnDefs: columnDefs,
  rowData: getData(),
  defaultColDef: {
    editable: true,
    flex: 1,
    minWidth: 100,
  },
};

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);
```

[Live example: Popup Editor Components](https://www.ag-grid.com/examples/cell-editors/popup-editor/typescript)

> **Note**
>
> If a custom cell editor creates its own popup that is anchored outside of the editor component (e.g. like a third-party date picker), then the popup element needs to have the `'ag-custom-component-popup'` CSS class. This allows the grid to determine correctly when to stop editing.

## Keyboard Navigation

In Custom Editors, 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.suppressKeyboardEvent()` 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, this is good for creating reusable cell editors.

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

```js
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';

eInputDomElement.addEventListener('keydown', event => {
    const key = event.key;

    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();
    }
})
```

### Option 2 - Suppress Keyboard Event

If you implement `colDef.suppressKeyboardEvent()`, you can tell the grid which events you want to 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.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `suppressKeyboardEvent` | `SuppressKeyboardEventFunc` |  | `false` | Allows the user to suppress certain keyboard events in the grid cell. |

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

colDef.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;
}
```

## Accessing Instances

After the grid has created an instance of an Editor Component 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 Editor that has nothing to do with the operation of the grid. Accessing Editors is done using the grid API `getCellEditorInstances(params)`.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `getCellEditorInstances` | `Function` |  |  | Returns the list of active cell editor instances. Optionally provide parameters to restrict to certain columns / row nodes. Modules (any of): [`TextEditorModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`LargeTextEditorModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`NumberEditorModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`DateEditorModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`CheckboxEditorModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`CustomEditorModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`SelectEditorModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`RichSelectModule`](https://www.ag-grid.com/javascript-data-grid/modules/). |

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.

An example of calling `getCellEditorInstances()` is as follows:

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

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.

#### Get Editor Instance

```ts
import {
  ClientSideRowModelModule,
  ColDef,
  CustomEditorModule,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberEditorModule,
  TextEditorModule,
  TextFilterModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import { getData } from "./data";
import { MySimpleEditor } from "./mySimpleEditor";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  NumberEditorModule,
  TextEditorModule,
  TextFilterModule,
  CustomEditorModule,
  ClientSideRowModelModule,
]);

const columnDefs: ColDef[] = [
  { field: "first_name", headerName: "First Name", width: 120, editable: true },
  { field: "last_name", headerName: "Last Name", width: 120, editable: true },
  {
    field: "gender",
    width: 100,
    cellEditor: MySimpleEditor,
  },
  {
    field: "age",
    width: 80,
    cellEditor: MySimpleEditor,
  },
  {
    field: "mood",
    width: 90,
    cellEditor: MySimpleEditor,
  },
  {
    field: "country",
    width: 110,
    cellEditor: MySimpleEditor,
  },
  {
    field: "address",
    width: 502,
    cellEditor: MySimpleEditor,
  },
];

let gridApi: GridApi;

const gridOptions: GridOptions = {
  columnDefs: columnDefs,
  defaultColDef: {
    editable: true,
    minWidth: 100,
    filter: true,
  },
  rowData: getData(),
  onGridReady: (params) => {
    setInterval(() => {
      const instances = gridApi!.getCellEditorInstances();
      if (instances.length > 0) {
        const instance = instances[0] as Partial<MySimpleEditor>;
        if (instance.myCustomFunction) {
          const result = instance.myCustomFunction();
          console.log(
            `found editing cell: row index = ${result.rowIndex}, column = ${result.colId}.`,
          );
        } else {
          console.log(
            "found editing cell, but method myCustomFunction not found, must be the default editor.",
          );
        }
      } else {
        console.log("found not editing cell.");
      }
    }, 2000);
  },
};

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);
```

[Live example: Get Editor Instance](https://www.ag-grid.com/examples/cell-editors/get-editor-instance/typescript)

## API Reference

### ICellEditorComp

Properties available on the `ICellEditorComp&lt;TData = any, TValue = any, TContext = any&gt;` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `getValue` | `Function` |  |  | Mandatory - Return the final value. Called by the grid once after editing is complete. |
| `refresh` | `Function` |  |  | Optional: Gets called with the latest cell editor params every time they update |
| `afterGuiAttached` | `Function` |  |  | Optional: A hook to perform any necessary operation just after the GUI for this component has been rendered on the screen. This method is called each time the edit component is activated. This is useful for any logic that requires attachment before executing, such as putting focus on a particular DOM element. |
| `isPopup` | `Function` |  |  | Optional: Gets called once after initialised. If you return true, the editor will appear in a popup, so is not constrained to the boundaries of the cell. This is great if you want to, for example, provide you own custom dropdown list for selection. Default is false (ie if you don't provide the method). |
| `getPopupPosition` | `Function` |  |  | Optional: Gets called once, only if isPopup() returns true. Return "over" if the popup should cover the cell, or "under" if it should be positioned below leaving the cell value visible. If this method is not present, the default is "over". |
| `isCancelBeforeStart` | `Function` |  |  | Optional: Gets called once after initialised. If you return true, the editor will not be used and the grid will continue editing. Use this to make a decision on editing inside the init() function, eg maybe you want to only start editing if the user hits a numeric key, but not a letter, if the editor is for numbers. |
| `isCancelAfterEnd` | `Function` |  |  | Optional: Gets called once after editing is complete. If your return true, then the new value will not be used. The editing will have no impact on the record. Use this if you do not want a new value from your gui, i.e. you want to cancel the editing. |
| `focusIn` | `Function` |  |  | Optional: If doing full line edit, then gets called when focus should be put into the editor |
| `focusOut` | `Function` |  |  | Optional: If doing full line edit, then gets called when focus is leaving the editor |
| `getValidationElement` | `Function` |  |  | Optional: Returns the element to use for validation feedback. Called by the grid in two contexts: `tooltip: true` → used as the anchor for validation tooltips. `tooltip: false` → receives the `invalid` CSS class for visual feedback. If omitted, the grid falls back to the cell element for inline editors. Popup editors that do not implement this will not show validation styles or tooltips. `tooltip` - Whether the element is for a tooltip or direct styling. Returns: An HTML element for feedback, or `null`/`undefined` to use default behavior. |
| `getValidationErrors` | `Function` |  |  | Optional: The error messages associated with the Editor |
| `getGui` | `Function` |  |  | Return the DOM element of your component, this is what the grid puts into the DOM |
| `destroy` | `Function` |  |  | Gets called once by grid when the component is being removed; if your component needs to do any cleanup, do it here |
| `init` | `Function` |  |  | The init(params) method is called on the component once. |

### ICellEditorParams

Properties available on the `ICellEditorParams&lt;TData = any, TValue = any, TContext = any&gt;` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `parseValue` | `Function` |  |  | Utility function to parse a value using the column's `colDef.valueParser` |
| `formatValue` | `Function` |  |  | Utility function to format a value using the column's `colDef.valueFormatter` |
| `value` | [`TValue \| null \| undefined`](https://www.ag-grid.com/javascript-data-grid/typescript-generics/#cell-value-tvalue) |  |  | Current value of the cell |
| `eventKey` | `string \| null` |  |  | Key value of key that started the edit, eg 'Enter' or 'F2' - non-printable characters appear here |
| `column` | [`Column`](https://www.ag-grid.com/javascript-data-grid/column-object/) |  |  | Grid column |
| `colDef` | [`ColDef`](https://www.ag-grid.com/javascript-data-grid/column-properties/) |  |  | Column definition |
| `node` | [`IRowNode`](https://www.ag-grid.com/javascript-data-grid/row-object/) |  |  | Row node for the cell |
| `data` | [`TData`](https://www.ag-grid.com/javascript-data-grid/typescript-generics/#row-data-tdata) |  |  | Row data |
| `rowIndex` | `number` |  |  | Editing row index |
| `cellStartedEdit` | `boolean` |  |  | If doing full row edit, this is true if the cell is the one that started the edit (eg it is the cell the use double clicked on, or pressed a key on etc). |
| `onKeyDown` | `Function` |  |  | callback to tell grid a key was pressed - useful to pass control key events (tab, arrows etc) back to grid - however you do |
| `stopEditing` | `Function` |  |  | Callback to tell grid to stop editing the current cell. Call with input parameter true to prevent focus from moving to the next cell after editing stops in case the grid property `enterNavigatesVerticallyAfterEdit=true`. Pass the originating keydown event when committing from a key press so that `enterNavigatesVerticallyAfterEdit` can move focus in the correct direction. |
| `eGridCell` | [`HTMLElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement) |  |  | A reference to the DOM element representing the grid cell that your component will live inside. Useful if you want to add event listeners or classes at this level. This is the DOM element that gets browser focus when selecting cells. |
| `getValidationErrors` | `Function` |  |  | Optional validation callback that will override the `getValidationErrors()` of Provided Editors. Use this to return your own custom errors. Returns: An array of strings containing the editor error messages, or `null` if the editor is valid. |
| `validate` | `Function` |  |  | Runs the Editor Validation. |
| `api` | [`GridApi`](https://www.ag-grid.com/javascript-data-grid/grid-api/) |  |  | The grid api. |
| `context` | [`TContext`](https://www.ag-grid.com/javascript-data-grid/typescript-generics/#context-tcontext) |  |  | Application context as set on `gridOptions.context`. |
