Skip to main content
Every edit in <Tally> is a mutation. It applies at once, goes to the source’s mutate, and undoes with Cmd/Ctrl + Z. See Mutations and undo for the model.

When cells are editable

A cell is editable when the source has the mutate capability and the column does not set editable: false. A read-only source turns every editing affordance off, including paste, fill, clear, the new row and CSV import. The default editors are a text input for text and numbers, a date input for dates, and a combobox for enums. See Custom renderers and editors to replace them.

Parsing

Every value goes through the column type’s parse. A currency column accepts $5k, a date column accepts 2026-01-15, and an enum column accepts a value or a label. An empty value becomes null. A value that does not parse is skipped, so the cell keeps its old value.

Validating in the source

The source is where a business rule rejects a change. Return accepted: false with one error per problem, and the grid reverts the mutation and drops it from history.
validate.ts
A source that throws is treated the same way, with the error message. CSV import shows the first error in the status banner. A rejected cell edit reverts the cell, and setCells returns the result with its errors.

Validating on the server

tally-server and tally/laravel validate every mutation request before it touches the database: unknown columns, columns with editable: false, values whose kind does not match the column, and rows without a key. A database error rejects the mutation with Mutation failed. validateMutationRequest(body, schema) in tally-protocol runs the same checks in your own handler. See Protocol.

New rows

grid.newRow() builds a blank row with a random UUID under the schema’s key field. Pass newRow to useGrid or createGrid when the key is computed or the row needs default values.