---
title: "Cell Editing Validation"
framework: vue
version: "36.1.0"
---

# Cell Editing Validation

## Standard Validation

The Grid provides built-in validation for all [Provided Cell Editors](https://www.ag-grid.com/vue-data-grid/provided-cell-editors/), such as the Text, Large Text, Number and Date editors. These editors support validation automatically by checking the constraints defined in the column configuration. For example:

- `Text` and `Large Text` editors will respect the `maxLength` property.
- `Number` editors validate against min and max constraints.
- `Date` editors ensure the value is a valid date string.

Validation is performed when editing ends, and the Grid will handle invalid values based on the selected [Validation Modes](#validation-modes).

#### Cell Editor Validation

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ClientSideRowModelApiModule,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  DateEditorModule,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberEditorModule,
  TextEditorModule,
  ValueFormatterParams,
  enableDevValidations,
} from "ag-grid-community";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  NumberEditorModule,
  TextEditorModule,
  DateEditorModule,
  ClientSideRowModelApiModule,
  ClientSideRowModelModule,
]);

interface IModifiedOlympicData extends IOlympicData {
  dateObj: Date | null;
}

const stringToDate = (date: string): Date | null => {
  const [day, month, year] = (date || "").split("/");
  if (day == null || month == null || year == null) {
    return null;
  }
  return new Date(Number(year), Number(month) - 1, Number(day));
};

const dateToIso = (date: string | null): string => {
  const [day, month, year] = (date || "").split("/");
  if (day == null || month == null || year == null) {
    return "";
  }
  return `${year}-${month}-${day}`;
};

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      v-model="rowData"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IModifiedOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      {
        field: "athlete",
        headerName: "Athlete (maxLength 10)",
        cellEditor: "agTextCellEditor",
        cellEditorParams: {
          maxLength: 10,
        },
      },
      {
        field: "age",
        headerName: "Age (>= 0 and <= 100)",
        cellEditor: "agNumberCellEditor",
        cellEditorParams: {
          min: 0,
          max: 100,
        },
      },
      {
        field: "dateObj",
        headerName: "Date (< 2009)",
        cellEditor: "agDateCellEditor",
        valueFormatter: (params: ValueFormatterParams<any, Date>) => {
          if (!params.value) {
            return "";
          }
          const month = params.value.getMonth() + 1;
          const day = params.value.getDate();
          return `${params.value.getFullYear()}-${month < 10 ? "0" + month : month}-${day < 10 ? "0" + day : day}`;
        },
        cellEditorParams: {
          max: new Date("2008-12-31"),
        },
      },
      {
        field: "date",
        headerName: "Date as String (> 2008)",
        cellEditor: "agDateStringCellEditor",
        cellEditorParams: {
          min: "2008-12-31",
        },
      },
    ]);
    const defaultColDef = ref<ColDef>({
      editable: true,
      cellDataType: false,
    });
    const rowData = ref<IModifiedOlympicData[]>(null);

    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) =>
        (rowData.value = data.map((rec: IOlympicData) => ({
          ...rec,
          date: dateToIso(rec.date),
          dateObj: stringToDate(rec.date),
        })));

      fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      rowData,
      onGridReady,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Cell Editor Validation](https://www.ag-grid.com/examples/cell-editing-validation/cell-editor-validation/vue3)

## Overriding Validation

To add custom validation logic to a Provided Editor, use the `getValidationErrors()` callback inside the `ICellEditorParams`. This allows you to define additional rules that are specific to your application.

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

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `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. |

```ts
<ag-grid-vue
    :columnDefs="columnDefs"
    /* other grid options ... */>
</ag-grid-vue>

this.columnDefs = [
    {
        field: 'athlete',
        cellEditorParams: {
            getValidationErrors: (params) => {
                const { value } = params;
                if (!value || value.length < 3) {
                    return ['The value has to be at least 3 characters long.'];
                }

                return null;
            },
        },
    },
];
```

If the callback returns errors, the Grid will show the errors in a tooltip when hovering the editor and discard the edit value before completing (depending on the [Validation Modes](#validation-modes)).

This is demonstrated in the following example, note that:

- `Athlete` has to be at least `3` characters.
- `Age` has to be different than `18`.

#### Cell Editor Validation Override

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ClientSideRowModelApiModule,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  IErrorValidationParams,
  ModuleRegistry,
  NumberEditorModule,
  TextEditorModule,
  enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

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

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      v-model="rowData"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      {
        field: "athlete",
        cellEditorParams: {
          getValidationErrors: (params: IErrorValidationParams) => {
            const { value } = params;
            if (!value || value.length < 3) {
              return ["The value has to be at least 3 characters long."];
            }
            return null;
          },
        },
      },
      {
        field: "age",
        cellEditorParams: {
          getValidationErrors: (params: IErrorValidationParams) => {
            const { value } = params;
            if (value != null && value == 18) {
              return ["Value has to be different than 18"];
            }
            return null;
          },
        },
      },
    ]);
    const defaultColDef = ref<ColDef>({
      editable: true,
    });
    const rowData = ref<IOlympicData[]>(null);

    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) => (rowData.value = data);

      fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      rowData,
      onGridReady,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Cell Editor Validation Override](https://www.ag-grid.com/examples/cell-editing-validation/cell-editor-validation-override/vue3)

## Validation Modes

The Grid supports two modes for handling invalid edits, configured via the grid option `invalidEditValueMode`:

| Mode | Description |
| --- | --- |
| `'revert'` (default) | Cancels the edit and reverts the cell to its original value if the value is invalid. |
| `'block'` | Prevents the editor from closing until a valid value is provided. Other editors cannot be started until the current edit is completed or cancelled. |

Use the `'block'` mode when you want to strictly enforce valid input before allowing the user to proceed.

```ts
<ag-grid-vue
    :invalidEditValueMode="invalidEditValueMode"
    /* other grid options ... */>
</ag-grid-vue>

this.invalidEditValueMode = 'block';
```

#### Cell Editor Validation Modes

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./styles.css";
import {
  ClientSideRowModelApiModule,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  EditValidationCommitType,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberEditorModule,
  TextEditorModule,
  enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

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

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="example-wrapper">
      <div class="example-header">
        <label>
          <span>Cell Editor Validation Mode: </span>
          <select id="select-validation-mode" v-on:change="onValidationModeSelect()">
            <option value="revert">revert</option>
            <option value="block">block</option>
          </select>
        </label>
      </div>
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        @grid-ready="onGridReady"
        :columnDefs="columnDefs"
        :defaultColDef="defaultColDef"
        :invalidEditValueMode="invalidEditValueMode"
        v-model="rowData"></ag-grid-vue>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      {
        field: "athlete",
        headerName: "Athlete (maxLength 10)",
        cellEditor: "agTextCellEditor",
        cellEditorParams: {
          maxLength: 10,
        },
      },
      {
        field: "age",
        headerName: "Age (>= 0 and <=100)",
        cellEditor: "agNumberCellEditor",
        cellEditorParams: {
          min: 0,
          max: 100,
        },
      },
    ]);
    const defaultColDef = ref<ColDef>({
      editable: true,
    });
    const invalidEditValueMode = ref<EditValidationCommitType>("revert");
    const rowData = ref<IOlympicData[]>(null);

    function onValidationModeSelect() {
      const value: "revert" | "block" =
        document.querySelector<HTMLSelectElement>("#select-validation-mode")
          ?.value as EditValidationCommitType;
      gridApi.value.setGridOption("invalidEditValueMode", value);
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) => (rowData.value = data);

      fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      invalidEditValueMode,
      rowData,
      onGridReady,
      onValidationModeSelect,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Cell Editor Validation Modes](https://www.ag-grid.com/examples/cell-editing-validation/cell-editor-validation-modes/vue3)

## Full Row Editing Validation

When using [Full Row Editing](https://www.ag-grid.com/vue-data-grid/cell-editing-full-row/), the Grid will validate each cell editor in the row individually, using the same mechanisms described in the previous sections.

In addition, the Grid can also perform cross-field validation by using the optional callback `getFullRowEditValidationErrors(params)`. This allows you to implement logic that checks relationships between fields — for example, ensuring that one field is greater than another.

This callback should return an array of error strings if the row is in an invalid state. If no errors are found, it should return `null`.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `getFullRowEditValidationErrors` | `GetFullRowEditValidationErrors` |  |  | Validates the Full Row Edit. Only relevant when `editType="fullRow"`. Modules (any of): [`TextEditorModule`](https://www.ag-grid.com/vue-data-grid/modules/), [`LargeTextEditorModule`](https://www.ag-grid.com/vue-data-grid/modules/), [`NumberEditorModule`](https://www.ag-grid.com/vue-data-grid/modules/), [`DateEditorModule`](https://www.ag-grid.com/vue-data-grid/modules/), [`CheckboxEditorModule`](https://www.ag-grid.com/vue-data-grid/modules/), [`CustomEditorModule`](https://www.ag-grid.com/vue-data-grid/modules/), [`SelectEditorModule`](https://www.ag-grid.com/vue-data-grid/modules/), [`RichSelectModule`](https://www.ag-grid.com/vue-data-grid/modules/). |

```ts
<ag-grid-vue
    :getFullRowEditValidationErrors="getFullRowEditValidationErrors"
    /* other grid options ... */>
</ag-grid-vue>

this.getFullRowEditValidationErrors = (params) => {
    const { data } = params;
    if (data.min > data.max) {
        return ['Min cannot be greater than Max'];
    }
    return null;
};
```

A row edit will only complete successfully if **both** the individual cell editors **and** the full-row validation return no errors.

This is demonstrated in the following example. Note the following validation rules:

- `Weight` has to be a positive value below `500`.
- `Height` has to be a positive value below `300`.
- **Full Row Edit Validation** ensures that the Body Mass Index (BMI), calculated using height and weight, is between `10` and `80`.

#### Full Row Editing Validation

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./styles.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  EditStrategyType,
  EditValidationCommitType,
  GetFullRowEditValidationErrors,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberEditorModule,
  SelectEditorModule,
  TextEditorModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
} from "ag-grid-enterprise";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

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

function getRowData() {
  const rowData = [
    { name: "Alice", weight: 68, height: 165 },
    { name: "Bob", weight: 85, height: 178 },
    { name: "Charlie", weight: 72, height: 172 },
    { name: "Diana", weight: 54, height: 160 },
    { name: "Ethan", weight: 90, height: 182 },
    { name: "Fiona", weight: 63, height: 168 },
    { name: "George", weight: 77, height: 175 },
    { name: "Hannah", weight: 59, height: 162 },
    { name: "Ian", weight: 95, height: 185 },
    { name: "Julia", weight: 70, height: 170 },
  ];
  return rowData;
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :editType="editType"
      :rowData="rowData"
      :invalidEditValueMode="invalidEditValueMode"
      :getFullRowEditValidationErrors="getFullRowEditValidationErrors"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi | null>(null);
    const columnDefs = ref<ColDef[]>([
      {
        field: "name",
      },
      {
        field: "weight",
        headerName: "Weight (kg)",
        cellDataType: "number",
        cellEditorParams: {
          min: 0,
          max: 500,
        },
      },
      {
        field: "height",
        headerName: "Height (cm)",
        cellDataType: "number",
        cellEditorParams: {
          min: 0,
          max: 300,
        },
      },
      {
        headerName: "BMI",
        cellDataType: "number",
        valueGetter: (params) => {
          const { weight, height } = params.data ?? {};
          if (!weight || !height) return null;
          const heightM = height / 100;
          return weight / (heightM * heightM);
        },
        valueFormatter: (params) => params.value?.toFixed(2),
        editable: false,
      },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      editable: true,
      cellDataType: false,
    });
    const editType = ref<EditStrategyType>("fullRow");
    const rowData = ref<any[] | null>(getRowData());
    const invalidEditValueMode = ref<EditValidationCommitType>("block");
    const getFullRowEditValidationErrors = ref<GetFullRowEditValidationErrors>(
      ({ editorsState }) => {
        const values = Object.fromEntries(
          editorsState.map(({ colId, newValue }) => [colId, newValue]),
        );
        const weight = parseFloat(values["weight"]);
        const height = parseFloat(values["height"]);
        const heightM = height / 100;
        const bmi = weight / (heightM * heightM);
        const errors: string[] = [];
        if (bmi < 10 || bmi > 80) {
          errors.push(
            `BMI value of ${bmi.toFixed(2)} is not realistic. Please verify the input.`,
          );
        }
        return errors.length ? errors : null;
      },
    );

    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      editType,
      rowData,
      invalidEditValueMode,
      getFullRowEditValidationErrors,
      onGridReady,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Full Row Editing Validation](https://www.ag-grid.com/examples/cell-editing-validation/full-row-editing-validation/vue3)

## Validation of Custom Editors

Custom Cell Editors can participate in the Grid's validation system by optionally implementing the following methods:

Properties available on the `ICellEditor&lt;TValue = any&gt;` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `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 |

These methods are called automatically before the Grid attempts to complete the edit. You can also manually trigger validation by calling the validate() method available in the cellEditorParams, for example:

```
cellEditorParams.validate();
```

This is useful if you want to validate input during editing, such as in response to an onInput event in the Custom Phone Editor.

#### Component Editor Validation

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./styles.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  CustomEditorModule,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberEditorModule,
  TextEditorModule,
  enableDevValidations,
} from "ag-grid-community";
import { RichSelectModule } from "ag-grid-enterprise";
import PhoneEditor from "./phoneEditorVue";
import { getData } from "./data";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

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

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :rowData="rowData"
      :defaultColDef="defaultColDef"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
    PhoneEditor,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "name" },
      {
        field: "phone",
        headerName: "Custom Phone Editor",
        cellEditor: "PhoneEditor",
      },
    ]);
    const rowData = ref<any[] | null>(getData());
    const defaultColDef = ref<ColDef>({
      editable: true,
      flex: 1,
      minWidth: 100,
    });

    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;
    };

    return {
      gridApi,
      columnDefs,
      rowData,
      defaultColDef,
      onGridReady,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Component Editor Validation](https://www.ag-grid.com/examples/cell-editing-validation/component-editor-validation/vue3)
