Tabulator Editable Grid with Validation — Free JS Snippet

Tabulator Editable Cells with Validation and Undo · Tables · Plain HTML, CSS & JS · Live preview

CategoryTables

What's included

Features

Typed editors: input, number with min/max/step and a labelled dropdown
Declarative validation rules including a regex for SKU format
validationMode "highlight" flags invalid cells without trapping the user
table.validate() as a gate before saving
Friendly messages built from the validationFailed rule type
Edited cells shaded and counted through the cellEdited event
Add and delete rows with full undo and redo history
Double-click to edit so casual clicks never change data

About this UI Snippet

Tabulator Editable Cells with Validation — HTML, CSS & JavaScript

Screenshot of the Tabulator Editable Cells with Validation and Undo snippet rendered live

Turning a table into a spreadsheet-style editor raises problems a read-only grid never has. What happens when someone types letters into a quantity column? How do they know which cells they changed? What if they delete the wrong row? Tabulator has answers to all of these as configuration, and this snippet wires them together into a complete edit-then-save workflow for a small product catalogue.

Editing starts with the editor property on each column. An input editor gives a text box, number gives a numeric field with min, max and step through editorParams, and list gives a dropdown whose values object maps stored values to labels — so the cell stores "in-stock" but shows "In stock". editTriggerEvent: 'dblclick' requires a double-click to start editing, which prevents accidental edits when people are just clicking around a table.

Validation is declared beside the editor as a validator array of rules: required, minLength:3, integer, min:0, max:9999, numeric, and even a regular expression for SKU format. The important choice is validationMode. The default is 'blocking', which keeps the cell stuck in edit mode until the value is valid — safe, but it traps users who want to move on. This snippet uses 'highlight', which lets the value in but marks the cell red with a tabulator-validation-fail class, and then makes validity a gate at save time: table.validate() returns true when everything passes, or an array of the failing cells. The validationFailed event supplies the failing rule, which the snippet translates into a plain-English message such as "SKU must look like ABC-123".

Change tracking is a small addition with a big effect. The cellEdited event adds a class that shades edited cells amber and records the row in a Set, so the message bar can say "2 rows changed — not saved yet", and saving clears the marks. Setting history: true makes Tabulator record every change so table.undo() and table.redo() work for edits, additions and deletions alike — which is the safety net that makes a one-click delete button acceptable. New rows are added with addRow(data, true) and the promise it returns is used to open the name cell for editing immediately.

Step by step

How to Use

  1. 1
    Edit a cellDouble-click a product name, quantity or price and type a new value. The cell shades amber to show it changed.
  2. 2
    Trigger a validation errorSet a quantity to a negative number or an SKU to "abc". The cell turns red and the message bar says why.
  3. 3
    Try to save with an errorPress Save changes while a cell is invalid. Saving is refused and the count of invalid cells is shown.
  4. 4
    Add and delete rowsUse Add product to insert a row, and the × button to delete one.
  5. 5
    Undo mistakesPress Undo to reverse the last edit, addition or deletion, and Redo to reapply it.

Real-world uses

Common Use Cases

📦
Inventory and catalogue editors
Let staff fix prices and stock levels in place, with typed editors and a labelled dropdown for fixed choices.
🧾
Budgeting and invoice lines
Edit amounts and quantities with rule-based validation, including a regular expression for a correctly formatted SKU.
🧹
Bulk data cleanup
Correct many records quickly in bulk cleanup tools, with dirty-cell tracking showing exactly which cells changed before anything is finally saved.
🎓
Validation mode comparison
See how validationMode: 'highlight' flags invalid cells without trapping the user, unlike blocking validation, and compare with the Tabulator sortable filterable grid.
↩️
Safe editing workflows
Add and delete rows with undo and redo available, and gate saving behind table.validate() so invalid data never leaves the grid.

Got questions?

Frequently Asked Questions

Blocking keeps the cell in edit mode until the value is valid. Highlight accepts the value but marks the cell invalid, so you can gate the save instead.

Call table.validate(). It returns true when everything passes, or an array of the invalid cells.

Set history: true in the options, then call table.undo() and table.redo().

Give the list editor a values object such as { "in-stock": "In stock" }; the key is stored and the label is displayed.

Listen for the cellEdited event and record the cell or row, or compare against your original data.

Add a rule such as "regex:^[A-Z]{3}-[0-9]{3}$" to the validator array.

Yes. Use the JSX, Vue, Angular or Tailwind export buttons on this page to convert the markup and styles. The behaviour comes from Tabulator, so in a framework project install it with npm install tabulator-tables (or react-tabulator) instead of the CDN tag, create it in useEffect / onMounted / ngAfterViewInit and wait for the tableBuilt event, and release it with destroy() when the component unmounts.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Ask an AI assistant like Claude to send the changed rows to an API with fetch, add a required-column marker in headers, or add row-level validation that compares two columns.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build an editable product grid with Tabulator 6 loaded from a CDN (script and CSS).

Requirements:
- Use history: true, validationMode: 'highlight' and editTriggerEvent: 'dblclick'.
- Define editable columns: name (input, required, minLength:3), SKU (regex ^[A-Z]{3}-[0-9]{3}$), quantity (number, integer, 0 to 9999), price (number with the money formatter, min 0.01) and status (list editor with labelled values), plus a delete-row column.
- On cellEdited shade the cell and count changed rows; on validationFailed show a plain-English message based on the failing rule.
- Add Add product (addRow then edit the name cell), Undo and Redo buttons, and a Save button that calls table.validate() and refuses to save when invalid cells exist.
- Show a status bar for unsaved changes, errors and successful saves.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Source Code

<div class="te-card">
  <div class="te-bar">
    <button type="button" class="te-btn" id="teAdd">+ Add product</button>
    <button type="button" class="te-btn" id="teUndo" title="Undo (Ctrl+Z)">&#8630; Undo</button>
    <button type="button" class="te-btn" id="teRedo" title="Redo (Ctrl+Y)">&#8631; Redo</button>
    <span class="te-hint">Double-click a cell to edit</span>
    <button type="button" class="te-save" id="teSave">Save changes</button>
  </div>
  <div id="teTable"></div>
  <div class="te-msg" id="teMsg" role="status" aria-live="polite">No changes yet.</div>
</div>