Interactive table generation JavaScript library with sorting, filtering, editing, formatting, and extensive customization capabilities
—
Interactive editing capabilities with validation, custom editors, and edit state management for dynamic data modification.
Methods for controlling cell editing behavior and state management.
/**
* Start editing cell (added to CellComponent by Edit module)
*/
edit(): void;
/**
* Cancel current cell editing operation
*/
cancelEdit(): void;
/**
* Set cell value programmatically
* @param value - New value for cell
* @param mutate - Apply mutators during value setting
* @returns Promise resolving when value is set
*/
setValue(value: any, mutate?: boolean): Promise<void>;
/**
* Get current cell value
* @returns Current cell value
*/
getValue(): any;
/**
* Get previous cell value before current edit
* @returns Previous cell value
*/
getOldValue(): any;
/**
* Get original cell value from initial data load
* @returns Initial cell value
*/
getInitialValue(): any;
/**
* Check if cell has been edited since last data load
* @returns True if cell has been modified
*/
isEdited(): boolean;
/**
* Clear edited flag for cell
*/
clearEdited(): void;
/**
* Restore cell to previous value
*/
restoreOldValue(): void;
/**
* Restore cell to initial value from data load
*/
restoreInitialValue(): void;Usage Examples:
// Get cell and start editing
const cell = table.getRow(1).getCell("name");
cell.edit();
// Programmatic value changes
await cell.setValue("New Name");
console.log("Current:", cell.getValue());
console.log("Previous:", cell.getOldValue());
console.log("Original:", cell.getInitialValue());
// Edit state management
if (cell.isEdited()) {
console.log("Cell has been modified");
cell.restoreOldValue(); // Undo changes
}
// Cancel editing
cell.cancelEdit();Navigation methods for moving between editable cells during editing sessions.
/**
* Navigate to previous editable cell
*/
navigatePrev(): void;
/**
* Navigate to next editable cell
*/
navigateNext(): void;
/**
* Navigate to cell to the left
*/
navigateLeft(): void;
/**
* Navigate to cell to the right
*/
navigateRight(): void;
/**
* Navigate to cell above
*/
navigateUp(): void;
/**
* Navigate to cell below
*/
navigateDown(): void;Usage Examples:
// Set up keyboard navigation
table.on("cellEdited", function(cell) {
// Auto-advance to next cell after edit
cell.navigateNext();
});
// Custom navigation logic
table.on("keyDown", function(e, cell) {
if (e.key === "Tab") {
e.preventDefault();
if (e.shiftKey) {
cell.navigatePrev();
} else {
cell.navigateNext();
}
}
});Tabulator provides numerous built-in editors for different data types and input scenarios.
interface EditorTypes {
/** Basic text input editor */
"input": {
/** Search functionality */
search?: boolean;
/** Input mask pattern */
mask?: string;
/** Select text on focus */
selectContents?: boolean;
/** Element attributes */
elementAttributes?: { [key: string]: string };
};
/** Multi-line text editor */
"textarea": {
/** Number of visible rows */
verticalNavigation?: "editor" | "table";
/** Element attributes */
elementAttributes?: { [key: string]: string };
};
/** Numeric input editor */
"number": {
/** Minimum value */
min?: number;
/** Maximum value */
max?: number;
/** Step increment */
step?: number;
/** Decimal places */
precision?: number;
/** Select text on focus */
selectContents?: boolean;
/** Vertical navigation */
verticalNavigation?: "editor" | "table";
};
/** Dropdown select editor */
"select": {
/** Option values */
values?: any[] | { [key: string]: string } | string;
/** Default empty option */
defaultValue?: any;
/** Clear button */
clearable?: boolean;
/** Allow filtering options */
searchable?: boolean;
/** Multiple selection */
multiselect?: boolean;
/** Max selections for multiselect */
maxSelections?: number;
};
/** Checkbox editor */
"tickCross": {
/** Value for checked state */
trueValue?: any;
/** Value for unchecked state */
falseValue?: any;
/** Allow indeterminate state */
tristate?: boolean;
/** Value for indeterminate state */
indeterminateValue?: any;
};
/** Date picker editor */
"date": {
/** Date format */
format?: string;
/** Minimum date */
min?: string;
/** Maximum date */
max?: string;
/** Vertical navigation */
verticalNavigation?: "editor" | "table";
};
/** Date and time picker editor */
"dateTime": {
/** DateTime format */
format?: string;
/** Minimum datetime */
min?: string;
/** Maximum datetime */
max?: string;
/** Time picker format */
timeFormat?: string;
/** Vertical navigation */
verticalNavigation?: "editor" | "table";
};
/** Time picker editor */
"time": {
/** Time format */
format?: string;
/** Vertical navigation */
verticalNavigation?: "editor" | "table";
};
/** Star rating editor */
"star": {
/** Number of stars */
stars?: number;
};
/** Range slider editor */
"range": {
/** Minimum value */
min?: number;
/** Maximum value */
max?: number;
/** Step increment */
step?: number;
};
}Create custom editors for specialized input requirements.
interface CustomEditor {
/**
* Create custom editor element
* @param cell - Cell component being edited
* @param onRendered - Callback when editor is rendered
* @param success - Callback to call with new value on successful edit
* @param cancel - Callback to call when edit is cancelled
* @param editorParams - Parameters from column definition
* @returns HTML element for the editor
*/
(
cell: CellComponent,
onRendered: (callback: Function) => void,
success: (value: any) => void,
cancel: (value: any) => void,
editorParams: any
): HTMLElement;
}Usage Examples:
// Column definitions with editors
const editableColumns = [
{
title: "Name",
field: "name",
editor: "input",
editorParams: {
search: true,
selectContents: true,
elementAttributes: { placeholder: "Enter full name" }
}
},
{
title: "Age",
field: "age",
editor: "number",
editorParams: {
min: 0,
max: 120,
step: 1,
selectContents: true
}
},
{
title: "Department",
field: "department",
editor: "select",
editorParams: {
values: {
"eng": "Engineering",
"sales": "Sales",
"marketing": "Marketing",
"hr": "Human Resources"
},
clearable: true,
searchable: true
}
},
{
title: "Active",
field: "active",
editor: "tickCross",
editorParams: {
trueValue: true,
falseValue: false
}
},
{
title: "Start Date",
field: "startDate",
editor: "date",
editorParams: {
format: "YYYY-MM-DD",
min: "2020-01-01",
max: "2030-12-31"
}
},
{
title: "Rating",
field: "rating",
editor: "star",
editorParams: {
stars: 5
}
}
];
// Custom color picker editor
function colorEditor(cell, onRendered, success, cancel, editorParams) {
const editor = document.createElement("input");
editor.type = "color";
editor.value = cell.getValue() || "#ffffff";
editor.style.padding = "3px";
editor.style.width = "100%";
editor.style.border = "1px solid #ccc";
onRendered(function() {
editor.focus();
});
editor.addEventListener("change", function() {
success(editor.value);
});
editor.addEventListener("blur", function() {
success(editor.value);
});
return editor;
}
// Use custom editor in column
{
title: "Color",
field: "color",
editor: colorEditor,
formatter: function(cell) {
const value = cell.getValue();
return `<div style="width: 20px; height: 20px; background-color: ${value}; border: 1px solid #ccc; display: inline-block;"></div> ${value}`;
}
}Configure when and how editing is initiated.
interface EditTriggers {
/** Click to edit */
editTrigger?: "click" | "dblclick" | "focus";
/** Manual edit trigger only */
editTriggerManual?: boolean;
}Validate cell values during editing with built-in and custom validators.
interface ValidationConfig {
/** Validation rules */
validator?: string | Function | Array<string | Function>;
/** Custom validation function */
validationFunction?: (value: any, validators: any[]) => boolean | string;
}
// Built-in validators
type BuiltInValidators =
| "required" // Value must not be empty
| "unique" // Value must be unique in column
| "integer" // Must be integer
| "float" // Must be float/decimal
| "numeric" // Must be numeric
| "string" // Must be string
| `min:${number}` // Minimum value/length
| `max:${number}` // Maximum value/length
| `minLength:${number}` // Minimum string length
| `maxLength:${number}` // Maximum string length
| "email" // Valid email format
| "url" // Valid URL format
| `regex:${string}`; // Match regex patternUsage Examples:
// Validation examples
const validatedColumns = [
{
title: "Email",
field: "email",
editor: "input",
validator: ["required", "email"]
},
{
title: "Age",
field: "age",
editor: "number",
validator: ["required", "integer", "min:0", "max:120"]
},
{
title: "Username",
field: "username",
editor: "input",
validator: ["required", "unique", "minLength:3", "maxLength:20", "regex:^[a-zA-Z0-9_]+$"]
},
{
title: "Password",
field: "password",
editor: "input",
editorParams: { elementAttributes: { type: "password" } },
validator: function(value) {
if (value.length < 8) return "Password must be at least 8 characters";
if (!/[A-Z]/.test(value)) return "Password must contain uppercase letter";
if (!/[0-9]/.test(value)) return "Password must contain number";
return true;
}
}
];
// Edit trigger configuration
const editableTable = new Tabulator("#editable-table", {
data: tableData,
columns: validatedColumns,
editTrigger: "dblclick", // Double-click to edit
validationMode: "highlight" // Highlight invalid cells
});// Enable/disable editing globally
table.on("tableBuilt", function() {
// Disable editing for specific conditions
if (user.role !== "admin") {
table.getColumns().forEach(column => {
column.updateDefinition({ editable: false });
});
}
});
// Conditional editing based on row data
const conditionalColumns = [
{
title: "Salary",
field: "salary",
editor: "number",
editable: function(cell) {
const rowData = cell.getRow().getData();
return rowData.role === "manager" || user.role === "admin";
}
}
];// Track edit history
const editHistory = [];
table.on("cellEdited", function(cell) {
editHistory.push({
row: cell.getRow().getIndex(),
field: cell.getField(),
oldValue: cell.getOldValue(),
newValue: cell.getValue(),
timestamp: new Date()
});
});
// Implement undo functionality
function undoLastEdit() {
if (editHistory.length > 0) {
const lastEdit = editHistory.pop();
const cell = table.getRow(lastEdit.row).getCell(lastEdit.field);
cell.setValue(lastEdit.oldValue);
}
}Install with Tessl CLI
npx tessl i tessl/npm-tabulator-tables