Interactive table generation JavaScript library with sorting, filtering, editing, formatting, and extensive customization capabilities
—
Comprehensive event handling for user interactions, data changes, and table lifecycle events with support for custom event dispatch.
Core methods for subscribing to and managing table events.
/**
* Subscribe to table event
* @param event - Event name to listen for
* @param callback - Function to execute when event fires
*/
on(event: string, callback: Function): void;
/**
* Unsubscribe from table event
* @param event - Event name to stop listening to
* @param callback - Specific callback to remove (optional, removes all if not provided)
*/
off(event: string, callback?: Function): void;
/**
* Dispatch custom event
* @param event - Event name to dispatch
* @param args - Arguments to pass to event handlers
*/
dispatchEvent(event: string, ...args: any[]): void;Usage Examples:
// Basic event subscription
table.on("rowClick", function(e, row) {
console.log("Row clicked:", row.getData());
});
// Multiple event handlers
table.on("cellEdited", handleCellEdit);
table.on("cellEdited", logCellChanges);
table.on("cellEdited", validateCellData);
// Remove specific handler
table.off("cellEdited", logCellChanges);
// Remove all handlers for event
table.off("rowClick");
// Dispatch custom event
table.dispatchEvent("customDataUpdate", { source: "api", count: 50 });Events related to table construction, destruction, and state changes.
interface LifecycleEvents {
/** Fired before table construction begins */
"tableBuilding": () => void;
/** Fired after table construction completes */
"tableBuilt": () => void;
/** Fired after table is completely destroyed */
"tableDestroyed": () => void;
/** Fired when table is redrawn */
"tableRedraw": (force: boolean) => void;
}Usage Examples:
table.on("tableBuilding", function() {
console.log("Starting table construction...");
showLoadingIndicator();
});
table.on("tableBuilt", function() {
console.log("Table ready!");
hideLoadingIndicator();
initializeCustomFeatures();
});
table.on("tableDestroyed", function() {
console.log("Table cleanup complete");
clearCustomEventListeners();
});Events triggered by data loading, changes, and manipulation operations.
interface DataEvents {
/** Fired before data loading begins */
"dataLoading": (data: any) => void;
/** Fired after data is loaded and processed */
"dataLoaded": (data: any[]) => void;
/** Fired when data changes occur */
"dataChanged": (data: any[]) => void;
/** Fired after data processing completes */
"dataProcessed": () => void;
/** Fired before data sorting */
"dataSorting": (sorters: any[]) => void;
/** Fired after data is sorted */
"dataSorted": (sorters: any[], rows: RowComponent[]) => void;
/** Fired before data filtering */
"dataFiltering": (filters: any[]) => void;
/** Fired after data is filtered */
"dataFiltered": (filters: any[], rows: RowComponent[]) => void;
}Usage Examples:
// Data loading events
table.on("dataLoading", function(data) {
console.log("Loading data...", data);
showProgressBar();
});
table.on("dataLoaded", function(data) {
console.log(`Loaded ${data.length} records`);
hideProgressBar();
updateRecordCount(data.length);
});
// Data change tracking
table.on("dataChanged", function(data) {
console.log("Data modified, auto-saving...");
autoSaveData(data);
});
// Filter and sort events
table.on("dataFiltered", function(filters, rows) {
updateStatusBar(`${rows.length} rows visible`);
});
table.on("dataSorted", function(sorters, rows) {
console.log("Data sorted by:", sorters);
});Events related to row operations, selection, and user interactions.
interface RowEvents {
/** Fired when row is added to table */
"rowAdded": (row: RowComponent) => void;
/** Fired when row is deleted from table */
"rowDeleted": (row: RowComponent) => void;
/** Fired when row data is updated */
"rowUpdated": (row: RowComponent) => void;
/** Fired when row is moved */
"rowMoved": (row: RowComponent) => void;
/** Fired when row is clicked */
"rowClick": (e: Event, row: RowComponent) => void;
/** Fired when row is double-clicked */
"rowDblClick": (e: Event, row: RowComponent) => void;
/** Fired when row context menu is triggered */
"rowContext": (e: Event, row: RowComponent) => void;
/** Fired when row is selected */
"rowSelected": (row: RowComponent) => void;
/** Fired when row is deselected */
"rowDeselected": (row: RowComponent) => void;
/** Fired when row selection changes */
"rowSelectionChanged": (data: any[], rows: RowComponent[]) => void;
/** Fired when mouse enters row */
"rowMouseEnter": (e: Event, row: RowComponent) => void;
/** Fired when mouse leaves row */
"rowMouseLeave": (e: Event, row: RowComponent) => void;
}Usage Examples:
// Row interaction events
table.on("rowClick", function(e, row) {
const data = row.getData();
if (data.id) {
window.location.href = `/users/${data.id}`;
}
});
table.on("rowDblClick", function(e, row) {
row.getCell("name").edit(); // Start editing name field
});
// Row data change events
table.on("rowAdded", function(row) {
console.log("New row added:", row.getData());
row.getElement().style.backgroundColor = "lightgreen";
setTimeout(() => {
row.getElement().style.backgroundColor = "";
}, 2000);
});
table.on("rowUpdated", function(row) {
console.log("Row updated:", row.getData());
markRowAsModified(row);
});
// Row selection events
table.on("rowSelectionChanged", function(data, rows) {
const count = rows.length;
document.getElementById("selected-count").textContent = `${count} selected`;
// Enable/disable bulk action buttons
toggleBulkActions(count > 0);
});Events for cell-level interactions, editing, and formatting.
interface CellEvents {
/** Fired when cell is clicked */
"cellClick": (e: Event, cell: CellComponent) => void;
/** Fired when cell is double-clicked */
"cellDblClick": (e: Event, cell: CellComponent) => void;
/** Fired when cell context menu is triggered */
"cellContext": (e: Event, cell: CellComponent) => void;
/** Fired when cell editing begins */
"cellEditing": (cell: CellComponent) => void;
/** Fired when cell editing is cancelled */
"cellEditCancelled": (cell: CellComponent) => void;
/** Fired when cell edit is completed */
"cellEdited": (cell: CellComponent) => void;
/** Fired when mouse enters cell */
"cellMouseEnter": (e: Event, cell: CellComponent) => void;
/** Fired when mouse leaves cell */
"cellMouseLeave": (e: Event, cell: CellComponent) => void;
}Usage Examples:
// Cell editing events
table.on("cellEditing", function(cell) {
console.log("Editing cell:", cell.getField());
cell.getElement().style.backgroundColor = "lightyellow";
});
table.on("cellEdited", function(cell) {
const field = cell.getField();
const newValue = cell.getValue();
const oldValue = cell.getOldValue();
console.log(`${field} changed from "${oldValue}" to "${newValue}"`);
// Validate and save
if (validateCellValue(field, newValue)) {
saveCellChange(cell.getRow().getData().id, field, newValue);
} else {
cell.restoreOldValue();
}
});
// Cell interaction events
table.on("cellClick", function(e, cell) {
if (cell.getField() === "email") {
window.open(`mailto:${cell.getValue()}`);
}
});Events related to column operations and interactions.
interface ColumnEvents {
/** Fired when column header is clicked */
"columnClick": (e: Event, column: ColumnComponent) => void;
/** Fired when column header is double-clicked */
"columnDblClick": (e: Event, column: ColumnComponent) => void;
/** Fired when column context menu is triggered */
"columnContext": (e: Event, column: ColumnComponent) => void;
/** Fired when column is moved */
"columnMoved": (column: ColumnComponent, columns: ColumnComponent[]) => void;
/** Fired when column is resized */
"columnResized": (column: ColumnComponent) => void;
/** Fired when column visibility changes */
"columnVisibilityChanged": (column: ColumnComponent, visible: boolean) => void;
/** Fired when column title is changed */
"columnTitleChanged": (column: ColumnComponent) => void;
}Events for pagination operations and navigation.
interface PageEvents {
/** Fired when page is loaded */
"pageLoaded": (pageno: number) => void;
/** Fired when page changes */
"pageChanged": (pageno: number) => void;
}// Prevent default behavior with validation
table.on("cellEditing", function(cell) {
const field = cell.getField();
const rowData = cell.getRow().getData();
if (field === "salary" && rowData.role !== "manager") {
cell.cancelEdit();
alert("Only managers can edit salaries");
return false; // Prevent editing
}
});
// Chain events for complex workflows
table.on("rowAdded", function(row) {
// Auto-assign ID for new rows
if (!row.getData().id) {
row.update({ id: generateUniqueId() });
}
});
table.on("rowUpdated", function(row) {
// Auto-update modified timestamp
row.update({ lastModified: new Date().toISOString() });
});// Define custom events for application logic
class TableManager {
constructor(table) {
this.table = table;
this.setupCustomEvents();
}
setupCustomEvents() {
// Custom validation event
this.table.on("customValidation", (data, callback) => {
fetch("/api/validate", {
method: "POST",
body: JSON.stringify(data)
})
.then(response => response.json())
.then(result => callback(result.isValid, result.errors));
});
// Custom save event
this.table.on("customSave", (data) => {
this.saveToServer(data);
});
}
triggerValidation(data) {
this.table.dispatchEvent("customValidation", data, (isValid, errors) => {
if (isValid) {
this.table.dispatchEvent("customSave", data);
} else {
this.displayErrors(errors);
}
});
}
}// Debounce rapid events
let saveTimeout;
table.on("cellEdited", function(cell) {
clearTimeout(saveTimeout);
saveTimeout = setTimeout(() => {
saveAllData();
}, 1000); // Save 1 second after last edit
});
// Batch event processing
const batchProcessor = {
events: [],
timeout: null,
add(event, data) {
this.events.push({ event, data, timestamp: Date.now() });
if (!this.timeout) {
this.timeout = setTimeout(() => {
this.processBatch();
}, 100);
}
},
processBatch() {
console.log(`Processing ${this.events.length} events`);
// Process all events together
this.events = [];
this.timeout = null;
}
};
table.on("cellEdited", (cell) => batchProcessor.add("cellEdited", cell));
table.on("rowUpdated", (row) => batchProcessor.add("rowUpdated", row));Install with Tessl CLI
npx tessl i tessl/npm-tabulator-tables