CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-tabulator-tables

Interactive table generation JavaScript library with sorting, filtering, editing, formatting, and extensive customization capabilities

Pending
Overview
Eval results
Files

validation.mddocs/

Data Validation

Comprehensive data validation system with built-in validators, custom validation functions, and flexible validation modes for ensuring data integrity.

Capabilities

Table Validation Methods

Core validation functions for managing table-wide validation state and operations.

/**
 * Validate all cells in the table
 * @returns Array of invalid CellComponent objects
 */
validate(): CellComponent[];

/**
 * Get all currently invalid cells
 * @returns Array of invalid CellComponent objects  
 */
getInvalidCells(): CellComponent[];

/**
 * Clear validation state for specific cell
 * @param cell - Cell to clear validation for
 */
clearCellValidation(cell: CellComponent): void;

Validation Configuration:

interface ValidationOptions {
  validationMode?: "blocking" | "highlighting" | "manual";
}

Column Validation

Column-level validation configuration and methods.

// Added to ColumnComponent by Validate module
/**
 * Validate all cells in this column
 * @returns Array of invalid CellComponent objects
 */
validate(): CellComponent[];

Column Validation Configuration:

interface ColumnDefinition {
  validator?: string | Function | Array<string | Function>;
  // ... other column options
}

Cell Validation

Cell-level validation state management and validation execution.

// Added to CellComponent by Validate module
/**
 * Check if cell value is valid
 * @returns True if valid, false if invalid
 */
isValid(): boolean;

/**
 * Validate this cell's current value
 * @returns True if valid, error message/object if invalid
 */
validate(): boolean | string | any;

/**
 * Clear validation state for this cell
 */
clearValidation(): void;

Row Validation

Row-level validation for validating all cells within a row.

// Added to RowComponent by Validate module  
/**
 * Validate all cells in this row
 * @returns Array of invalid CellComponent objects
 */
validate(): CellComponent[];

Usage Examples:

import { Tabulator } from "tabulator-tables";

// Table with validation configuration
const table = new Tabulator("#table", {
  data: [
    { name: "", email: "invalid-email", age: 15, score: 150 },
    { name: "Bob", email: "bob@example.com", age: 25, score: 85 }
  ],
  columns: [
    {
      title: "Name", 
      field: "name",
      validator: ["required", "minLength", "unique"],
      editor: "input"
    },
    {
      title: "Email",
      field: "email", 
      validator: ["required", "regex"],
      validatorParams: {
        regex: /^[^\s@]+@[^\s@]+\.[^\s@]+$/
      },
      editor: "input"
    },
    {
      title: "Age",
      field: "age",
      validator: ["required", "integer", "min", "max"],
      validatorParams: {
        min: 18,
        max: 120
      },
      editor: "number"
    },
    {
      title: "Score", 
      field: "score",
      validator: function(cell, value, parameters) {
        return value >= 0 && value <= 100 ? true : "Score must be between 0-100";
      },
      editor: "number"
    }
  ],
  validationMode: "highlighting" // highlight invalid cells but allow editing
});

// Validate entire table
const invalidCells = table.validate();
if (invalidCells.length > 0) {
  console.log(`Found ${invalidCells.length} invalid cells`);
  invalidCells.forEach(cell => {
    console.log(`Invalid: ${cell.getField()} = ${cell.getValue()}`);
  });
}

// Get currently invalid cells
const currentlyInvalid = table.getInvalidCells();
console.log(`Currently invalid cells: ${currentlyInvalid.length}`);

// Validate specific column
const nameColumn = table.getColumn("name");
const invalidNameCells = nameColumn.validate();

// Validate specific row
const firstRow = table.getRow(0);
const invalidRowCells = firstRow.validate();

// Validate specific cell
const emailCell = table.getRow(0).getCell("email");
const isEmailValid = emailCell.isValid();
const emailValidationResult = emailCell.validate();

// Clear validation for specific cell
emailCell.clearValidation();

Built-in Validators

Tabulator provides comprehensive built-in validators for common validation scenarios.

/**
 * Built-in validator functions
 */
interface BuiltinValidators {
  /**
   * Must be an integer value
   */
  integer(cell: CellComponent, value: any, parameters?: any): boolean;
  
  /**
   * Must be a float value
   */
  float(cell: CellComponent, value: any, parameters?: any): boolean;
  
  /**
   * Must be a numeric value
   */
  numeric(cell: CellComponent, value: any, parameters?: any): boolean;
  
  /**
   * Must be a string value
   */
  string(cell: CellComponent, value: any, parameters?: any): boolean;
  
  /**
   * Must be alphanumeric characters only
   */
  alphanumeric(cell: CellComponent, value: any, parameters?: any): boolean;
  
  /**
   * Must be less than or equal to maximum value
   */
  max(cell: CellComponent, value: any, parameters: number): boolean;
  
  /**
   * Must be greater than or equal to minimum value
   */
  min(cell: CellComponent, value: any, parameters: number): boolean;
  
  /**
   * Must start with specified string
   */
  starts(cell: CellComponent, value: any, parameters: string): boolean;
  
  /**
   * Must end with specified string
   */
  ends(cell: CellComponent, value: any, parameters: string): boolean;
  
  /**
   * String must be at least minimum length
   */
  minLength(cell: CellComponent, value: any, parameters: number): boolean;
  
  /**
   * String must be at most maximum length
   */
  maxLength(cell: CellComponent, value: any, parameters: number): boolean;
  
  /**
   * Value must be in provided list
   */
  in(cell: CellComponent, value: any, parameters: any[] | string): boolean;
  
  /**
   * Must match provided regular expression
   */
  regex(cell: CellComponent, value: any, parameters: string | RegExp): boolean;
  
  /**
   * Value must be unique in this column
   */
  unique(cell: CellComponent, value: any, parameters?: any): boolean;
  
  /**
   * Value is required (not empty, null, or undefined)
   */
  required(cell: CellComponent, value: any, parameters?: any): boolean;
}

Validator Usage Examples:

// Single validator
{
  title: "Age",
  field: "age", 
  validator: "required"
}

// Multiple validators
{
  title: "Username", 
  field: "username",
  validator: ["required", "minLength", "alphanumeric", "unique"],
  validatorParams: {
    minLength: 3
  }
}

// Validator with parameters
{
  title: "Score",
  field: "score",
  validator: ["required", "numeric", "min", "max"],
  validatorParams: {
    min: 0,
    max: 100
  }
}

// Regex validator
{
  title: "Phone",
  field: "phone",
  validator: "regex",
  validatorParams: "^\\+?[1-9]\\d{1,14}$" // E.164 format
}

// In list validator
{
  title: "Status",
  field: "status", 
  validator: "in",
  validatorParams: ["active", "inactive", "pending"]
}

Custom Validators

Create custom validation functions for application-specific validation requirements.

/**
 * Custom validator function signature
 * @param cell - CellComponent being validated
 * @param value - Current cell value
 * @param parameters - Validation parameters
 * @returns True if valid, error message/object if invalid
 */
type ValidatorFunction = (
  cell: CellComponent, 
  value: any, 
  parameters?: any
) => boolean | string | any;

Custom Validator Examples:

// Custom email validator
function emailValidator(cell, value, parameters) {
  if (!value) return true; // Allow empty values
  
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return emailRegex.test(value) ? true : "Please enter a valid email address";
}

// Age range validator with context
function ageValidator(cell, value, parameters) {
  const rowData = cell.getRow().getData();
  const minAge = parameters.min || 0;
  const maxAge = parameters.max || 120;
  
  if (value < minAge) {
    return `Age must be at least ${minAge}`;
  }
  
  if (value > maxAge) {
    return `Age cannot exceed ${maxAge}`;
  }
  
  // Additional business logic
  if (rowData.role === "manager" && value < 25) {
    return "Managers must be at least 25 years old";
  }
  
  return true;
}

// Cross-field validation
function passwordConfirmValidator(cell, value, parameters) {
  const rowData = cell.getRow().getData();
  const password = rowData.password;
  
  return value === password ? true : "Passwords do not match";
}

// Async validator (returns Promise)
function uniqueUsernameValidator(cell, value, parameters) {
  if (!value) return true;
  
  return fetch(`/api/check-username/${encodeURIComponent(value)}`)
    .then(response => response.json())
    .then(data => data.unique ? true : "Username already exists");
}

// Usage in column definitions
const table = new Tabulator("#table", {
  columns: [
    {
      title: "Email",
      field: "email",
      validator: emailValidator,
      editor: "input"
    },
    {
      title: "Age", 
      field: "age",
      validator: ageValidator,
      validatorParams: { min: 18, max: 65 },
      editor: "number"
    },
    {
      title: "Confirm Password",
      field: "confirmPassword", 
      validator: passwordConfirmValidator,
      editor: "input"
    },
    {
      title: "Username",
      field: "username",
      validator: [uniqueUsernameValidator, "required", "minLength"],
      validatorParams: { minLength: 3 },
      editor: "input"
    }
  ]
});

Validation Modes

Configure how validation errors are handled and displayed.

type ValidationMode = "blocking" | "highlighting" | "manual";

Validation Mode Examples:

// Blocking mode - prevent invalid edits
const strictTable = new Tabulator("#strict-table", {
  validationMode: "blocking", // Default mode
  columns: [
    {
      title: "Required Field",
      field: "required_field", 
      validator: "required",
      editor: "input"
    }
  ]
});

// Highlighting mode - allow edits but highlight invalid cells
const flexibleTable = new Tabulator("#flexible-table", {
  validationMode: "highlighting",
  columns: [
    {
      title: "Optional Field",
      field: "optional_field",
      validator: "numeric", 
      editor: "input"
    }
  ]
});

// Manual mode - validation only when explicitly called
const manualTable = new Tabulator("#manual-table", {
  validationMode: "manual",
  columns: [
    {
      title: "Manual Validation",
      field: "manual_field",
      validator: "required",
      editor: "input" 
    }
  ]
});

// Manually trigger validation
document.getElementById("validate-btn").addEventListener("click", () => {
  const invalid = manualTable.validate();
  if (invalid.length > 0) {
    alert(`Found ${invalid.length} validation errors`);
  } else {
    alert("All data is valid!");
  }
});

Events

Validation-related events for responding to validation state changes.

// Validation events
table.on("validationFailed", function(cell, value, validators) {
  console.log("Validation failed:", cell.getField(), value, validators);
});

table.on("validationPassed", function(cell, value) {
  console.log("Validation passed:", cell.getField(), value);
});

Types

interface ValidatorParams {
  [key: string]: any;
  min?: number;
  max?: number;
  minLength?: number; 
  maxLength?: number;
  regex?: string | RegExp;
}

interface ValidationResult {
  valid: boolean;
  error?: string | any;
}

Install with Tessl CLI

npx tessl i tessl/npm-tabulator-tables

docs

cell-editing.md

clipboard.md

column-management.md

data-management.md

data-sorting.md

data-trees.md

event-system.md

filtering-search.md

history-undo.md

import-export.md

index.md

pagination.md

range-selection.md

row-grouping.md

table-construction.md

validation.md

tile.json