It supports pagination, sorting, filtering, global search, inline editing, row selection, actions, responsive columns, and configurable cell formatting.
The component works through the native <data-grid> custom element and ES modules.
Static HTML tables can provide the initial rows and column definitions, while remote datasets can come from an HTTP endpoint or a custom JavaScript data source.
Features
- Local HTML tables and server-backed datasets.
- Server-side pagination, sorting, filtering, and search.
- Inline cell editing with validation.
- Checkbox and radio row selection.
- Row actions and bulk actions.
- Responsive columns and expandable row details.
- Resizable, reorderable, autosized, and frozen columns.
- Date, datetime, number, and boolean formatting.
- CSS custom properties and density presets.
- RTL layouts and configurable UI labels.
How To Use It
Installation
Load the core stylesheet and ES module build from a CDN.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/data-grid-component@3/dist/data-grid.min.css" > <script type="module" src="https://cdn.jsdelivr.net/npm/data-grid-component@3/dist/data-grid.min.js"> </script>
All import the package via NPM and import it into your project:
npm install data-grid-component
import { DataGrid } from "data-grid-component";
import "data-grid-component/styles";
Basic Usage
A regular HTML table can provide the initial columns and rows. The <data-grid> element takes control of later rendering after the component loads.
When neither src nor dataSource is configured, rows in <tbody> become the local dataset. Each tr[data-row-key] supplies the row identifier.
A td[data-value] stores the machine-readable value. Its displayed HTML can contain formatted text, badges, <time> elements, or other presentation markup. If data-value is absent, the component reads the cell text as a string.
The <th data-field> element defines a column. Supported column attributes include data-sortable, data-filterable, data-filter, data-responsive, data-hidden, data-editable, data-editable-type, data-transform, data-format, data-align, data-width, and data-min-width.
<data-grid
sortable
filterable
searchable
page-size="10"
>
<table>
<thead>
<tr>
<th data-field="customer" data-sort="asc">Customer</th>
<th data-field="email">Email</th>
<th data-field="plan" data-filter="select">Plan</th>
</tr>
</thead>
<tbody>
<tr data-row-key="101">
<td>Mira Chen</td>
<td>mira@example.com</td>
<td data-value="pro">Pro</td>
</tr>
<tr data-row-key="102">
<td>Daniel Brooks</td>
<td>daniel@example.com</td>
<td data-value="starter">Starter</td>
</tr>
</tbody>
</table>
</data-grid>
Load Data From a Server
Set src when the grid should request rows from an HTTP endpoint.
<data-grid src="/api/customers" sortable filterable searchable selectable page-sizes="10,25,50" row-key="id" > </data-grid>
Server responses use a rows array and a total record count.
{
"rows": [
{
"id": 301,
"name": "Avery Johnson",
"status": "active"
}
],
"total": 142
}
Optional metadata can supply filter values and other server-driven data.
{
"rows": [],
"total": 142,
"meta": {
"filters": {
"status": [
{
"value": "active",
"text": "Active"
}
]
}
}
}
Pagination, sorting, filtering, and search state form the current query. Remote data sources receive that state when the grid loads a new result.
Constant request parameters can be supplied through params when the constructor API is used.
import { DataGrid } from "data-grid-component";
const customerGrid = new DataGrid({
src: "/api/customers",
params: {
region: "west"
},
sortable: true,
filterable: true,
searchable: true,
pageSizes: [20, 50, 100]
});
document.querySelector("#customer-grid").appendChild(customerGrid);
Lazy-Load Remote Data
The default loading mode is eager. Set loading="lazy" when the initial request should wait until the grid approaches the viewport.
<data-grid src="/api/archive" loading="lazy" sortable searchable > </data-grid>
Create Columns in JavaScript
The built-in formatters support boolean, date, datetime, and number.
date represents a calendar date. datetime represents an instant with time information. Number formatting uses Intl.NumberFormat, while date values use Intl.DateTimeFormat.
import { DataGrid } from "data-grid-component";
const grid = new DataGrid({
src: "/api/orders",
sortable: true,
filterable: true,
columns: [
{
field: "orderId",
title: "Order",
width: 120
},
{
field: "created",
title: "Created",
format: "date"
},
{
field: "total",
title: "Total",
format: "number",
formatOptions: {
style: "currency",
currency: "USD"
},
align: "end"
},
{
field: "paid",
title: "Paid",
format: "boolean"
}
]
});
document.body.appendChild(grid);
Inline Editing
Set editable on a column when its cells should enter edit mode.
import { DataGrid } from "data-grid-component";
const grid = new DataGrid({
columns: [
{
field: "product",
title: "Product"
},
{
field: "stock",
title: "Stock",
editable: true,
editableType: "number",
validate(value) {
return Number(value) >= 0 || "Stock cannot be negative";
}
}
]
});
Listen for the edit event when an edited value is committed.
grid.addEventListener("edit", function (event) {
const { data, value, field, column } = event.detail;
console.log(data, value, field, column);
});
Row Selection
Enable checkbox selection with the selectable attribute.
<data-grid src="/api/invoices" selectable select-visible-only="false" > </data-grid>
single-select switches the selection control to radio buttons.
<data-grid src="/api/accounts" single-select > </data-grid>
selectVisibleOnly defaults to true. The select-all control therefore selects rows visible in the current result by default.
The selection API can inspect or modify selection state.
const state = grid.getSelectionState(); grid.selectRow(row); grid.deselectRow(row); grid.toggleRow(row); grid.selectAll(); grid.clearSelection();
getSelectionState() returns an object with mode, ids, and except. This representation also works with server-backed datasets where the complete dataset does not exist in the browser.
Row Actions
Row actions can represent view, edit, approve, delete, or other record-specific operations.
import { DataGrid } from "data-grid-component";
const grid = new DataGrid({
src: "/api/members",
rowClick: "action",
actions: [
{
name: "view",
label: "View",
intent: "primary",
href: row => `/members/${row.id}`,
default: true
},
{
name: "delete",
label: "Delete",
intent: "danger",
confirm: row => `Delete ${row.name}?`
}
]
});
The action event reports the resolved action and row.
grid.addEventListener("action", function (event) {
const {
action,
name,
row,
rowKey,
rowIndex,
trigger
} = event.detail;
console.log(name, rowKey);
});
Actions can also come from declarative table markup.
<data-grid row-actions>
<table>
<thead>
<tr>
<th data-field="customer">Customer</th>
<th data-actions>Actions</th>
</tr>
</thead>
<tbody>
<tr data-row-key="501">
<td>Jordan Lee</td>
<td data-actions>
<a data-action="view" href="/customers/501">
View
</a>
<button
data-action="delete"
data-confirm="Delete this customer?"
>
Delete
</button>
</td>
</tr>
</tbody>
</table>
</data-grid>
Row Click Behavior
The rowClick option accepts three modes.
actionruns the row’s default action.selecttoggles row selection.nonedisables automatic row-click behavior.
A cancelable rowClick event fires before the configured behavior.
grid.addEventListener("rowClick", function (event) {
if (event.detail.row.locked) {
event.preventDefault();
}
});
Custom content can opt out through data-row-click-ignore.
<span data-row-click-ignore> Custom interactive content </span>
Responsive Columns
Enable responsive column handling with the responsive option.
<data-grid responsive responsive-start-open > </data-grid>
Set a column’s responsive value to control its priority.
columns: [
{
field: "customer",
title: "Customer",
responsive: 0
},
{
field: "phone",
title: "Phone",
responsive: 2
},
{
field: "notes",
title: "Notes",
responsive: 5
}
]
responsiveStartOpen displays hidden column values immediately inside the responsive detail area.
<data-grid responsive responsive-start-open responsive-toggle="false" > </data-grid>
Row Details
rowDetails renders application content beneath a row. Responsive hidden-column content and application row details can share the disclosure control. Set responsiveToggle: false when responsive values should stay open while application details use their own disclosure.
const grid = new DataGrid({
rowDetails: ({ row }) => {
const panel = document.createElement("div");
panel.textContent = `Account owner: ${row.owner}`;
return panel;
}
});
Scrollable Grid
A constrained grid height creates an internal scroll viewport.
.customer-results {
max-height: 70vh;
}
<data-grid class="customer-results" src="/api/customers" > </data-grid>
Column Formatting
Four built-in format values handle common data types.
const columns = [
{
field: "enabled",
format: "boolean"
},
{
field: "birthday",
format: "date"
},
{
field: "lastLogin",
format: "datetime"
},
{
field: "revenue",
format: "number",
formatOptions: {
style: "currency",
currency: "USD"
}
}
];
A column can also specify alignment and sizing independently.
{
field: "revenue",
format: "number",
align: "end",
minWidth: 100,
width: 140
}
Column Widths and Wrapping
minWidth acts as the minimum width. width specifies the preferred width. A column with no preferred width shares the available space.
Enable automatic measurement for widthless columns with autosize.
<data-grid autosize></data-grid>
Long text stays on one line by default. Set wrap for the entire grid or for individual columns.
columns: [
{
field: "title"
},
{
field: "description",
wrap: true
}
]
A frozen column can stay pinned to the logical start edge.
columns: [
{
field: "customer",
width: 220,
frozen: "start"
},
{
field: "email",
width: 280
}
]
Horizontal column snapping is available through snapColumns.
<data-grid snap-columns></data-grid>
Styling and Customization
The core stylesheet uses --dg-* custom properties for colors, controls, spacing, borders, selection states, and sizing.
data-grid {
--dg-bg: #ffffff;
--dg-color: #202124;
--dg-accent: #6750a4;
--dg-header-bg: #f7f5fa;
--dg-border-color: #ddd8e4;
--dg-row-hover-bg: #f9f7fc;
--dg-radius: 6px;
}
Available theme variables:
--dg-bg: Table and menu surfaces.--dg-color: Primary text.--dg-muted-color: Secondary text and placeholders.--dg-border-color: Main borders and separators.--dg-accent: Interactive accent.--dg-accent-soft: Soft accent background.--dg-focus-ring: Focus ring.--dg-header-bg: Header and footer background.--dg-header-color: Header text.--dg-filter-bg: Filter controls background.--dg-row-stripe-bg: Striped row background.--dg-row-hover-bg: Row hover background.--dg-row-selected-bg: Selected row background.--dg-row-selected-hover-bg: Selected row hover background.--dg-row-border-color: Row separators.--dg-control-bg: Buttons, inputs, and select backgrounds.--dg-control-color: Control text.--dg-control-border-color: Control borders.--dg-danger-bg: Error and danger background.--dg-danger-color: Error and danger text.--dg-danger-border-color: Error and danger borders.--dg-cell-padding-inline: Horizontal cell padding.--dg-cell-padding-block: Vertical cell padding.--dg-header-padding-y: Header vertical padding.--dg-control-height: Filter and footer control height.--dg-selection-column-width: Selection column width.--dg-actions-column-width: Collapsed actions column width.--dg-radius: Grid, control, and menu corner radius.
The density option changes the component spacing presets.
Supported values: compact, default, and comfortable.
<data-grid density="compact"></data-grid>
State selectors:
data-grid[data-loading] {}
data-grid[data-error] {}
data-grid[data-empty] {}
data-grid tr[data-selected] {}
data-grid td[data-editing] {}
data-grid td[data-invalid] {}
Configuration Options
src(String, default""): URL for a remote data endpoint.params(Object, default{}): Constant HTTP parameters sent with requests.dataSource(DataSource): Custom data source instance.loading(String, default"eager"): Initial loading mode. Acceptseagerorlazy.columns(Column[], default[]): Column definitions.rowKey(String | Function, default"id"): Stable row identifier.rowLabel(String | Function): Accessible row label.sortable(Boolean, defaultfalse): Enables column sorting.filterable(Boolean, defaultfalse): Displays column filters.selectable(Boolean, defaultfalse): Enables checkbox row selection.singleSelect(Boolean, defaultfalse): Enables radio-button selection.selectVisibleOnly(Boolean, defaulttrue): Limits select-all to visible rows.actions(Action[], default[]): Client-defined row actions.rowActions(Boolean, defaultfalse): Displays an actions column even when static actions are absent.actionRenderer(Function): Global action content renderer.rowClick(String, default"action"): Controls data-row clicks withaction,select, ornone.collapseActions(Boolean, defaultfalse): Groups actions in a native popover where supported.bulkActions(BulkAction[], default[]): Actions that operate on current selection.resizable(Boolean, defaultfalse): Enables column resizing.reorder(Boolean, defaultfalse): Enables drag-based column reordering.menu(Boolean, defaultfalse): Enables the column menu.responsive(Boolean, defaultfalse): Enables responsive column behavior.responsiveToggle(Boolean, defaulttrue): Displays the responsive disclosure control.responsiveStartOpen(Boolean, defaultfalse): Starts responsive detail rows expanded.rowDetails(Function): Renders application content for expanded rows.rowDetailsStartOpen(Boolean, defaultfalse): Starts application row details expanded.autosize(Boolean, defaultfalse): Measures widthless columns and assigns calculated widths.autoheight(Boolean, defaulttrue): Fills the grid height on the final page.autohidePager(Boolean, defaultfalse): Hides pagination when every row fits.wrap(Boolean, defaultfalse): Permits multi-line data cells.snapColumns(Boolean, defaultfalse): Enables proximity-based horizontal column snapping.pageSizes(Number[], default[10,25,50,100,250]): Available page-size choices.showPageSize(Boolean, defaulttrue): Displays the page-size selector.filterDelay(Number, default300): Text-filter debounce delay in milliseconds.searchable(Boolean, defaultfalse): Displays the global search field.searchPlaceholder(String, default""): Global search placeholder.searchDelay(Number, default300): Global search debounce delay in milliseconds.minSearchLength(Number, default0): Minimum search length before applying a query.density(String, default"default"): Row spacing preset.saveState(Boolean, defaultfalse): Persists query and column visibility state.errorMessage(String, default""): Message displayed after a load failure.noData(String, default""): Message displayed for an empty result.caption(String, default""): Table caption and accessible dataset name.initialQuery(QueryState): Initial query object.initialResult(PageResult): Initial result rendered before an asynchronous load.validate(Function): Grid-level editor validator.debug(Boolean, defaultfalse): Logs grid actions in DevTools.dir(String, default"ltr"): Text direction.id(String): Custom grid identifier.
HTML Attributes
src loading page page-size sortable filterable searchable search-placeholder search-delay min-search-length filter-delay responsive responsive-toggle responsive-start-open row-details-start-open selectable single-select select-visible-only row-click row-key row-label collapse-actions save-state no-data error-message page-sizes row-actions reorder menu wrap snap-columns autosize resizable autoheight autohide-pager show-page-size debug dir density
A bare Boolean attribute represents true.
<data-grid src="/api/customers" sortable filterable searchable selectable row-click="select" row-key="customerId" min-search-length="2" page-sizes="10,25,50" no-data="No matching customers" > </data-grid>
Column Options
field(String): Data property used by the column.title(String): Column heading. Defaults tofield.id(String): Stable column identifier. Defaults tofield.width(Number): Preferred column width.class(String): Class applied to header and body cells.attr(String): Writes the field value to a row attribute.hidden(Boolean): Hides the column.sortable(Boolean): Controls sorting for the column.filterable(Boolean): Controls filtering for the column.transform(String | Function): Transforms values before presentation.minWidth(Number): Minimum column width.align(String): Usesstart,center, orendalignment.format(String): Usesboolean,date,datetime, ornumber.formatOptions(Object): Options passed to the correspondingIntlformatter.editable(Boolean): Enables inline editing.editableType(String): Input type used during editing.validate(Function): Validates an edited value.responsive(Number): Responsive priority.0keeps the column visible.filterType(String): Usestext,select,boolean,number, ordate.filterList(FilterOption[]): Values used by a select filter.firstFilterOption(FilterOption): First empty select-filter item.filterMultiple(Boolean): Uses a multi-value select filter where browser support permits it.renderHeaderCell(Function): Custom header-cell renderer.renderFilterCell(Function): Custom filter-cell renderer.renderCell(Function): Custom body-cell renderer.cellClass(String | Function): Class applied to body cells for each row.wrap(Boolean): Overrides the grid-wide cell wrapping preference.frozen(String): Set to"start"to pin a column to the logical start edge.
Action Options
name(String): Action identifier.label(String): Button text and accessible label.intent("default" | "primary" | "danger"): Visual action intent.href(String | Function): Renders the action as a link.class(String): Custom action class.visible(Function): Controls visibility for each row.disabled(Boolean | Function): Blocks an action.render(Function): Custom action content renderer.confirm(Boolean | String | Function): Requests confirmation before dispatch.default(Boolean): Marks the primary row action.
API Methods
// Read a snapshot of the current query state.
grid.query;
// Read the current page.
grid.page;
// Read rows, total result count, and metadata.
grid.rows;
grid.total;
grid.meta;
// Read loading state and the last error.
grid.loading;
grid.error;
// Merge query values and reload.
grid.setQuery({
page: 2,
pageSize: 50
});
// Restore the initial query and reload.
grid.resetQuery();
// Reload the current query.
grid.refresh();
grid.load();
// Read normalized columns for the current render cycle.
grid.getColumns();
// Change column visibility.
grid.showColumn("email");
grid.hideColumn("email");
// Read available values for a select filter.
grid.getFilterOptions(column);
// Read server-aware selection state.
grid.getSelectionState();
// Test one row's selection state.
grid.isRowSelected(row);
// Change one row's selection state.
grid.selectRow(row);
grid.deselectRow(row);
grid.toggleRow(row);
// Select or clear rows.
grid.selectAll();
grid.clearSelection();
// Read selected rows available on the current page.
grid.getSelection();
// Update the global search value.
grid.setSearch("active");
grid.clearSearch();
// Update a row in the current result.
grid.updateRow(42, {
status: "approved"
});
// Remove a row from a mutable local dataset.
grid.removeRow(42);
// Navigate through pages.
grid.getFirst();
grid.getPrev();
grid.getNext();
grid.getLast();
// Clear active column filters.
grid.clearFilters();
// Change sorting.
grid.sortAsc("name");
grid.sortDesc("created");
grid.sortNone("created");
// Register plugin constructors.
DataGrid.registerPlugins({
CustomPlugin
});
// Read or replace global UI labels.
DataGrid.getLabels();
DataGrid.setLabels({
noData: "Nothing found"
});
// Fetch labels from a JSON file.
DataGrid.loadLabels("/locales/fr.json");
// Refresh labels on one connected grid.
grid.updateLabels();
Events
// Fires when the custom element connects.
grid.addEventListener("connected", function (event) {
console.log(event);
});
// Fires when the custom element disconnects.
grid.addEventListener("disconnected", function (event) {
console.log(event);
});
// Fires after a data request fails.
grid.addEventListener("loadError", function (event) {
console.log(event.detail);
});
// Fires when row selection changes.
grid.addEventListener("selectionChange", function (event) {
console.log(event.detail.selectionState);
});
// Fires when a column becomes visible or hidden.
grid.addEventListener("columnVisibility", function (event) {
console.log(event.detail.col, event.detail.visibility);
});
// Fires after column resizing.
grid.addEventListener("columnResized", function (event) {
console.log(event.detail.col, event.detail.width);
});
// Fires after column reordering.
grid.addEventListener("columnReordered", function (event) {
console.log(event.detail.col, event.detail.from, event.detail.to);
});
// Fires after the header renders.
grid.addEventListener("headerRendered", function (event) {
console.log(event);
});
// Fires after the body renders.
grid.addEventListener("bodyRendered", function (event) {
console.log(event);
});
// Fires for each rendered row.
grid.addEventListener("rowRendered", function (event) {
console.log(event.detail.rowData, event.detail.tr);
});
// Fires before automatic row-click behavior.
// Calling preventDefault() cancels that behavior.
grid.addEventListener("rowClick", function (event) {
console.log(event.detail.row, event.detail.rowKey);
});
// Fires after a row action.
grid.addEventListener("action", function (event) {
console.log(
event.detail.action,
event.detail.name,
event.detail.row,
event.detail.rowKey,
event.detail.rowIndex,
event.detail.trigger
);
});
// Fires after a bulk action.
grid.addEventListener("bulkAction", function (event) {
console.log(
event.detail.action,
event.detail.name,
event.detail.selection,
event.detail.query,
event.detail.trigger
);
});
// Fires when an edit is committed.
// The event can be canceled.
grid.addEventListener("edit", function (event) {
console.log(
event.detail.data,
event.detail.value,
event.detail.field,
event.detail.column
);
});
// Fires when row details open or close.
grid.addEventListener("rowDetailsToggle", function (event) {
console.log(
event.detail.row,
event.detail.rowKey,
event.detail.expanded
);
});
Translations
UI labels can be replaced globally.
DataGrid.setLabels({
noData: "No records",
booleanTrue: "Yes",
booleanFalse: "No"
});
A JSON translation file can also be loaded at runtime.
await DataGrid.loadLabels("/locales/es.json");
Call updateLabels() when one connected grid needs to refresh its rendered labels.
grid.updateLabels();
Alternatives
- Advanced Data Grid/Table Library in Vanilla JavaScript – VanillaGrid
- Interactive And Customizable Data Table/Grid Web Component – Active Table
- Add Sortable and Filterable Functionalities to HTML Tables with the Action Table Web Component
- Editable Spreadsheet Style Data Grid Library – simple-data-table
The post Sortable, Editable, Filterable Data Grid Web Component – data-grid.js appeared first on CSS Script.
Discover more from RSS Feeds Cloud
Subscribe to get the latest posts sent to your email.
