Build your first table.
v1.1.1Go from an array of data to a searchable, interactive table. Start with your framework, then add the features your application needs.
Install the package
#Use an existing TypeScript application with a bundler. Select a framework to see its install command and starter files. The wrappers use the same table engine and options.
npm install wts-data-table @wts-data-table/angularWorks with standalone Angular 17–22 applications. The wrapper updates data in place and destroys the table with the component.
Read the complete Angular guide: editing, selection, server data, and lifecycle →
Add this to your application’s global stylesheet (for example, styles.css or styles.scss). For Next.js, load it from the root layout or global stylesheet.
@import 'wts-data-table/styles.css';Integrate your framework
#These two files give you typed columns, stable row IDs, search, selection, and pagination. The same data file works with all four integrations.
1 Define your rows and columns
import type { DataTableOptions } from 'wts-data-table';
export interface Project {
id: string;
name: string;
status: string;
budget: number;
}
export const projects: Project[] = [
{ id: 'p1', name: 'Website redesign', status: 'In progress', budget: 24000 },
{ id: 'p2', name: 'Customer portal', status: 'Planning', budget: 18000 },
{ id: 'p3', name: 'Analytics dashboard', status: 'Complete', budget: 32000 }
];
export const columns: DataTableOptions<Project>['columns'] = [
{ accessor: 'name', header: 'Project' },
{ accessor: 'status', header: 'Status', filterVariant: 'select' },
{ accessor: 'budget', header: 'Budget', dataType: 'number' }
];2 Mount the Angular component
import { Component } from '@angular/core';
import {
WtsDataTableAngularComponent,
type WtsAngularDataTableOptions
} from '@wts-data-table/angular';
import { columns, projects, type Project } from './table-data';
@Component({
selector: 'app-project-table',
standalone: true,
imports: [WtsDataTableAngularComponent],
template: `<wts-data-table-angular
[data]="projects"
[options]="options"
/>`
})
export class ProjectTableComponent {
readonly projects = projects;
readonly options: WtsAngularDataTableOptions<Project> = {
columns,
getRowId: row => row.id,
ariaLabel: 'Project delivery',
showGlobalFilter: true,
selectionMode: 'multiple',
initialState: { pagination: { pageSize: 10 } }
};
} Import ProjectTableComponent into its parent component and use <app-project-table /> in the parent template.
Choose a renderer
#Use Complete for your first integration. Select another renderer when you need precise control over the bundle or your rendered UI.
Complete
Start herewts-data-tableFull compatibility renderer. Use this first when feature coverage matters more than the smallest bundle.
Base
wts-data-table/baseTree-shakable renderer where optional behavior is added through exact feature imports.
Lite
wts-data-table/liteCompact read-heavy renderer with sorting, filtering, paging, grouping, selection, responsive overflow, and virtualization.
Core
wts-data-table/coreDOM-free row model and state engine for applications that own every rendered element.
Example: compose features with Base
import { DataTable } from 'wts-data-table/base';
import { selectionFeature } from 'wts-data-table/features/selection';
import { responsiveFeature } from 'wts-data-table/features/responsive';
import 'wts-data-table/base.css';
new DataTable({
...options,
features: [selectionFeature(), responsiveFeature()]
}); Use your existing options object with a host, data, and columns. See the bundle-size guide for composition choices.
Feature guide
#Find the option or import for a capability, understand when to use it, and continue to a live example or a focused guide.
Find and understand data
Turn a large row set into a useful answer.
Sorting
initialState.sorting / setSorting()Order by one or several typed columns with custom comparators when needed.
Global search
showGlobalFilterProvide one quick search across every searchable column.
Column filters
columnFiltersUse text, select, boolean, range, date, date-time, and time filters per column.
Advanced filters
advancedFilteringBuild nested AND/OR rules for complex business queries.
SearchPanes
searchPanesShow faceted values and cascading live counts locally or from a server.
Grouping
showGrouping / state.groupingBuild expandable nested groups from headers or a grouping drop zone.
Aggregates
aggregation / summaryRowsCalculate count, sum, average, min, max, or custom group and footer totals.
Pivot models
wts-data-table/pivotCreate DOM-free cross-tab dimensions, values, subtotals, and grand totals.
Select and change data
Support application workflows without losing stable row identity.
Row selection
selectionModeChoose none, single, or multiple selection using stable IDs.
Bulk actions
bulkActionsAct on selected rows or an all-filtered selection without loading every record.
Cell and range selection
cellSelectionSelect cells, rows, columns, and rectangular ranges.
Inline editing
editing / onEditCommitValidate and persist keyboard-accessible optimistic edits with rollback.
AutoFill and paste
autoFillCopy or continue series across editable ranges and accept TSV input.
Batch edit history
wts-data-table/edit-historyValidate atomic multi-cell changes and provide bounded undo and redo.
CRUD editor
wts-data-table/crudCreate, edit, delete, upload, and bulk-edit through several form layouts.
Tree and detail rows
getSubRows / rowExpansionDisplay nested data, lazy children, or master-detail content.
Ordering and pinning
rowReordering / rowPinningMove rows with pointer or keyboard and keep important rows visible.
Control presentation
Adapt the table to product layout, viewport, and export needs.
Column layout
columnMenu / showColumnManagerResize, reorder, hide, auto-size, and pin columns.
Responsive details
responsiveCollapse lower-priority columns into accessible inline or popover details.
Sticky sections
stickyHeader / stickyFooterKeep multi-row headers and summary footers in view.
Grouped and temporal columns
headerGroup / filterVariantBuild nested headers and typed date, date-time, and time controls.
Buttons
buttonsAdd copy, CSV, Excel, PDF, print, columns, nested commands, and custom actions.
Custom content
cell / layout / pluginsRender safe text or DOM nodes and place features into layout slots.
Exports
wts-data-table/exportExport to clipboard, CSV, JSON, XLSX, PDF, or semantic print HTML.
Saved views
wts-data-table/persistenceStore versioned state or encode it into shareable URL parameters.
Themes and tokens
theme / --wts-table-*Use framework adapters and 87 supported CSS custom properties.
Localization and RTL
wts-data-table/i18nLoad locale packs, negotiate fallback, format values, and apply RTL.
Scale and integrate
Choose the data and rendering strategy for the workload.
Adaptive pagination
pagination / pageSizesUse numbered pages, first/last controls, page jumps, and adaptive ranges.
Virtualization
virtualizationMount only visible rows and columns while preserving semantic table markup.
Manual server data
manualFiltering / manualSorting / manualPaginationKeep UI state in the table while an API owns querying and row counts.
Async data source
wts-data-table/data-sourceAdd debouncing, cancellation, caching, stale-response protection, and status.
Unified server adapter
wts-data-table/serverShare authenticated transports, retries, cache, errors, and telemetry across rows and facets.
Database adapters
@wts-data-table/serverTranslate allowlisted requests into PostgreSQL, MySQL, SQLite, Knex, or Prisma queries.
Cursor and infinite loading
createDataTableCursorDataSourceController()Append opaque cursor pages from an observer, button, or framework effect.
Remote SearchPanes
searchPanes.loadFacetsLoad authenticated server facets with cancellation and cascading counts.
Transactions
applyTransaction()Add, update, and remove identified rows without replacing all data.
Web Component
wts-data-table/elementUse the complete renderer from standards-based custom elements.
Feature plug-ins
wts-data-table/pluginInstall validated behavior with manifests, dependency resolution, and cleanup.
Accessibility
ariaLabel / ariaDescriptionUse semantic tables, labelled controls, keyboard workflows, and live status.
Build a production configuration
# Extend your starter with typed filters, sorting, bulk actions, and a summary. Wrapper components receive the same options without element or data.
const table = new DataTable<Project>({
element: '#project-table',
ariaLabel: 'Project delivery',
data: projects,
getRowId: (row) => row.id,
columns: [
{ accessor: 'name', header: 'Project', responsive: 'always' },
{ accessor: 'status', header: 'Status', filterVariant: 'select' },
{ accessor: 'budget', header: 'Budget', dataType: 'number', aggregation: 'sum' }
],
initialState: {
pagination: { pageSize: 25 },
sorting: [{ id: 'name', direction: 'asc' }]
},
showGlobalFilter: true,
columnFilters: { mode: 'collapsible' },
columnMenu: true,
selectionMode: 'multiple',
bulkActions: true,
responsive: { breakpoint: 720, details: 'inline' },
pagination: { mode: 'pages', showPageJump: true },
summaryRows: { label: 'Total', columns: { budget: 'sum' }, scope: 'filtered' },
onStateChange: (state, reason) => console.log(reason, state)
});Virtualization reduces the rendered DOM. Server processing keeps the full dataset outside browser memory. They solve different problems and can be used together.
Read the server integration guide →Own state and lifecycle
#Use the existing controller to change data or view state. These calls are independent examples; replace the application values with your own records.
const state = table.getState();
const selected = table.getSelectedRows();
table.setGlobalFilter('platform');
table.setSorting([{ id: 'budget', direction: 'desc' }]);
table.setPageSize(50);
table.setData(nextProjects, totalRowCount);
table.applyTransaction({
add: [newProject],
update: [{ id: changed.id, data: changed }],
remove: [deletedId]
});
await table.ready();
await table.destroyAsync();setColumnFilter()setGrouping()setRowExpanded()pinRow()setColumnVisibility()replaceState()reset()render()Updating data changes rows in place. Replacing the options object remounts the controller. Keep options stable and let the wrapper handle cleanup on unmount.
Understand wrapper lifecycle →Troubleshooting common integration issues
- The table is unstyled
- Import the matching stylesheet globally. Complete uses
styles.css; Base usesbase.css; Lite useslite.css. - Selection disappears after changing data
- Set
getRowIdto a stable, unique record ID. Avoid array positions as IDs for sortable or changing data. - The table resets on every render
- Keep the options object reference stable. In React, create it outside the component or with
useMemo. - A detail row repeats the parent data
- Use
renderDetailPanelfor custom details. Real child rows requiregetSubRowsorloadSubRows.
Licensed advanced features
# Advanced features are included in wts-data-table. Import the feature you need and provide a verified license. Explore a working demonstration before integrating it.
Card view
Responsive cards with synchronized search, pagination, and selection. Requires an active subscription with the card-view feature.
wts-data-table/card-viewView demonstration →Advanced row model
Bounded external windows and server-owned row spaces.
wts-data-table/remote · wts-data-table/remote-viewportView demonstration →Indexed search
Indexed and database-aware filtering for large collections.
wts-data-table/search · wts-data-table/search-filtersView demonstration →Background export
Durable asynchronous exports that outlive a browser request.
wts-data-table/export-jobs · wts-data-table/durable-exportView demonstration →Worker processing
Move data processing off the UI thread.
wts-data-table/worker-engine · wts-data-table/worker-tableView demonstration →Live data
Apply ordered real-time changes from WebSocket or custom transports.
wts-data-table/live-data · wts-data-table/live-transportsView demonstration →Server analytics
Build server-backed pivot and analytical queries.
wts-data-table/pivot-controller · wts-data-table/pivot-builderView demonstration →Spreadsheet formulas
Parse, calculate, edit, and project workbook formulas.
wts-data-table/formula-engine · wts-data-table/formula-editorView demonstration →Collaborative editing
Synchronize concurrent editing through application transports.
wts-data-table/collaboration-client · wts-data-table/collaboration-tableView demonstration →Governed editing
Apply review, policy, audit, and controlled-change workflows.
wts-data-table/governance-client · wts-data-table/governance-panelView demonstration →Report designer
Build reusable report definitions and report interfaces.
wts-data-table/report-controller · wts-data-table/report-designerView demonstration →import { connectDataTableLicense } from 'wts-data-table/license';
import { createRemoteRowModel } from 'wts-data-table/remote';
const license = await connectDataTableLicense({ licenseKey: deploymentKey });
const rows = createRemoteRowModel({
license,
origin: window.location.origin,
...options
}); The token and options come from your application. See license integration for feature claims and pricing and licensing to request a quote, access, or renewal.
Developer guides
#Continue with integration patterns, design choices, and the boundaries your application owns.