demo D283
Validation declared on the column
An invalid edit vetoed with an announced inline error, from rules stated as data
validation: { required, min, max, pattern, oneOf }
The configuration
'declarative-validation': () => ({
rows: orders(5_000),
config: {
rowKey: 'id',
selection: 'multiple',
edit: true,
columns: [
orderCols.id,
{
...orderCols.reference,
edit: true,
validation: {
required: true,
pattern: '^(CHG|INC|REQ)-\\d{4}$',
messages: { pattern: 'Use CHG, INC or REQ followed by four digits.', required: 'A reference is required.' },
},
},
{
...orderCols.team,
edit: true,
validation: { required: true, oneOf: ['Core', 'Platform', 'Edge', 'Field'], messages: { oneOf: 'Pick one of the four teams.' } },
},
{
...orderCols.circuits,
edit: true,
validation: { required: true, min: 1, max: 40, messages: { min: 'At least one circuit.', max: 'Forty circuits at most.' } },
},
{
...orderCols.budget,
edit: true,
validation: {
min: 0,
messages: { min: 'A budget cannot be negative.' },
crossField: (value: unknown, row: unknown) => {
const rec = (row && ((row as any).data ?? row)) as Record<string, unknown>;
const circuits = Number(rec?.circuits ?? 0);
const n = Number(value);
return n <= circuits * 5_000
? true
: `At ${circuits} circuits the cap is ${(circuits * 5_000).toLocaleString('en-GB')}.`;
},
},
},
],
},
foot: [
'rules declared as data on the column: required, pattern, range, one-of, cross-field',
'try REQ-12 in Reference, or 0 in Circuits: the edit is vetoed with an announced error',
'a corrected value clears the mark; a value your code writes is never gated',
],
}),
Validation stated as data, enforced before the value lands
A grid that lets people edit needs to say what a good value looks like. Lattice Grid takes those rules as data on the column: validation accepts required, min and max, minLength and maxLength, a pattern, a oneOf list, and a crossField predicate for a rule that reads the rest of the row. Each rule is checked against a new value before it is written. A failing value is vetoed, so the cell keeps its old value and nothing half-valid ever lands, and the cell is marked with the grid’s own invalid state, an error that is announced to a screen reader rather than shown only as a red border. Correct the value and the mark clears.
Declaring the rules rather than writing them as a function keeps the constraints in one readable place, checkable outside the render path, and lets a rule carry its own message so a person sees “Use CHG, INC or REQ followed by four digits” instead of a generic refusal. Only a person’s edit is gated: a value written by your own code or arriving from a live feed is treated as the authority and lands untouched, so validation guards the keyboard without fighting your data flow.
How do I stop a grid accepting an invalid edit?
Declare the rules on the column under validation: required for a value that may not be blank, min and max for a number or date range, pattern for a shape the whole value must match, oneOf for a fixed set, and crossField for a rule that compares against other fields on the same row. A failing edit is vetoed before it is written, the cell is marked with an announced inline error, and a corrected value clears the mark. Give a rule its own message through messages so the reason is specific rather than generic.