ExamplesEditing & Validation
Cross-field
Row-level rules with validateRow. Judged on the row after a whole write gesture commits.
A rule that spans two columns: End must stay at or after Start. A per-column validate
cannot express that reliably. It runs mid-gesture, against whatever the row looked like at
that moment. validateRow runs once per touched row, after the whole write gesture
commits, so a pasted block of Start+End pairs is judged as one state.
Make an End time earlier than its Start (edit one cell, or paste both): the End cell gets flagged with the row-level message and the value still commits. Set the row consistent again and the flag clears.
pnpm dlx shadcn@latest add @gridcn/data-grid-cross-field-demo
The contract
<DataGrid
{...grid}
validateRow={(row) => (row.end < row.start ? { end: "End must be at or after Start" } : null)}
/>- Return
columnId -> messageto mark cells, ornullwhen the row is fine. - The row the callback receives already has all of the gesture's cells applied.
- Messages land in the same per-cell error display as server errors
(ring, tint, hover tooltip,
aria-invalid). And the values still commit: the same stance as server errors, no rollback. - A later write that makes the row consistent clears the verdict, even when it writes a different column than the marked one.
- It does not run on row insert/duplicate (a fresh row is expected to be incomplete), on
row deletion, or on a
dataarray you replace yourself. It must be synchronous.
Behavior reference
- Cross-field rules: validateRow: the full contract
- Server errors: the display treatment
validateRowreuses