Validation
Overview
rs-grid validates a cell edit before it is committed. Validation runs in two layers, checked in order:
- Declarative rules (
ColumnDef::rules: Vec<ValidationRule>) — the recommended way to validate. Built-in rules cover the common cases (Required,MinLength,MaxLength,Range,OneOf), plus aCustomescape hatch. - Legacy validator (
ColumnDef::validator: Option<CellValidator>) — a free-form closure, still supported for backward compatibility. It only runs once every rule has passed.
Validation is enforced inside GridState::apply, not just at the UI layer —
so it holds for every consumer (native tests, the canvas renderer, any
future custom renderer). It's also checked outside an edit session: pasting
skips invalid target cells (see Paste validation below), and the canvas
renderer flags any cell whose current value fails validation even when it's
never been edited (see At-rest indicator below).
Adding rules
Builder sugar on ColumnDef covers the common cases:
Or set the full list at once with ValidationRule directly, e.g. for a
Custom rule:
ValidationRule variants:
Rules run in order, first failure wins. Once all rules pass, the legacy
validator (if set) still runs:
Revert or block: InvalidEditMode
GridModel::invalid_edit_mode (default Revert) controls what happens when
CommitEdit fails validation:
Set it at build time:
or toggle it at runtime with GridCommand::SetInvalidEditMode(mode).
Both modes emit CommandOutput::ValidationError { row, col_key, message }.
Live feedback while typing
GridCommand::ValidateEdit { value } re-checks the in-progress edit's
pending value without committing — it's a no-op without an active edit
and creates no undo entry. rs-grid-web dispatches it automatically on every
keystroke, so the in-progress edit always reflects the current validation
state, not just the last commit attempt.
Read the live state on demand:
Some((row, col_key, message)) while the in-progress edit is invalid,
None otherwise.
Listening to validation
There are two callbacks — pick based on when you need to react:
rs-grid does not impose a validation-error widget (no built-in tooltip component) — it exposes the raw state so you can build one with your own framework/CSS.
Positioning a custom validation UI
GridCanvas::cell_client_rect(row, col_key) returns the cell's client-space
rectangle (left, top, width, height) in CSS pixels relative to the page —
ready to position a position: fixed tooltip or banner next to the failing
cell:
Returns None if col_key doesn't exist. It's geometry only — it doesn't
check whether the cell is currently scrolled into view.
At-rest indicator
A cell can be invalid without ever being edited — e.g. loaded that way from
the data source. The canvas renderer checks every visible cell's current
value against ColumnDef::validate_value and, on failure, draws a themed
border (Theme::invalid_cell_border / --rs-grid-invalid-cell-border)
around it — no click or edit session required. This is separate from (and
doesn't wait for) the inline editor's invalid style described above; it
fires purely from the cell's current value.
Transparent invalid_cell_border (alpha 0) disables the indicator
entirely, same convention as locked_cell_bg.
Hover tooltip for invalid cells
Hovering an at-rest-invalid cell shows a tooltip — a single DOM element reused across every cell (not one per invalid cell, so the cost is the same whether one cell or thousands are invalid), positioned automatically over the hovered cell. rs-grid renders no visual of its own for it: the class is entirely yours, so you can reproduce daisyUI's tooltip directly:
tooltip-open (or an equivalent always-open modifier) is required — this
element never receives a real :hover from the mouse (it sits on top of
the canvas with pointer-events: none), so rs-grid opens/closes it itself
via its own display toggle rather than relying on CSS :hover. Without a
class set, the tooltip element exists but is invisible.
The validation message itself is exposed as the standard data-tip
attribute, which daisyUI (and any CSS using content: attr(data-tip))
reads directly — you never need to duplicate the message text yourself.
To check a cell's at-rest validity outside of hovering (e.g. for a custom
indicator), use canvas.cell_validation_error(row, col_key) -> Option<String> — independent of any active edit session, unlike
validation_error() above.
Paste validation
GridCommand::PasteAt validates each target cell's incoming value before
writing it — a cell whose pasted value fails validation is silently skipped
(the write doesn't happen), while the rest of the pasted block still
applies. This mirrors how Excel and AG Grid handle the same case: neither
blocks a paste outright, and when a rejection exists it's always per-cell,
never all-or-nothing.
GridCommand::CutSelection clears cells by writing an empty string — still
a write, so it's validated the same way: a cell whose rules reject an empty
value (e.g. .required()) keeps its original value instead of being
cleared. The copied text on the clipboard is unaffected either way — cut
always copies the full original values first.
Native title tooltip fallback
By default, the inline edit <input> gets a native title attribute
reflecting the current validation message — a zero-config browser tooltip
that needs no integration work. Disable it once you wire up a custom UI, so
the two don't compete:
Behaviour
- Validation runs on user edits (
CommitEdit/ValidateEdit) and onPasteAt(see Paste validation above). Direct programmatic writes viaGridModel::set_cellstill bypass it — that's the lowest-level API and intentionally has no validation layer of its own. Selecteditors are validated too — the selected option's value is checked like any other.- Rules and the legacy validator are synchronous. For async validation
(e.g. a server check), commit optimistically and revert with
GridCommand::Undoif the check fails server-side. Revertmode creates no undo entry;Blockmode doesn't either, since the edit session never closes on failure.
See also
- Editing — editing lifecycle and editor types
- ColumnDef API —
ValidationRule/CellValidatortype reference - GridCommand API —
ValidateEdit,SetInvalidEditMode - Undo / Redo — undo stack behaviour

