Skip to content

Getting Started

Using a framework? Jump directly to Angular, React, or Vue.

  1. Install the package

    Terminal window
    npm install @toolbox-web/grid
  2. Import and use

    import '@toolbox-web/grid'; // registers <tbw-grid>
    import { queryGrid } from '@toolbox-web/grid'; // typed DOM helper
  3. Add the grid to your HTML

    <tbw-grid id="my-grid" style="height: 400px;"></tbw-grid>

Define columns directly in HTML — great for static layouts and quick prototyping:

<tbw-grid style="height: 400px;">
<tbw-grid-column field="id" header="ID" type="number" sortable></tbw-grid-column>
<tbw-grid-column field="name" header="Name"></tbw-grid-column>
<tbw-grid-column field="email" header="Email"></tbw-grid-column>
</tbw-grid>

Set rows from JavaScript or via the rows HTML attribute (JSON). See Light DOM Columns for the full attribute reference.

Skip column configuration entirely — the grid creates columns from your data:

import '@toolbox-web/grid';
import { queryGrid } from '@toolbox-web/grid';
const grid = queryGrid('#my-grid');
grid.rows = [
{ id: 1, name: 'Alice Johnson', email: 'alice@example.com', active: true },
{ id: 2, name: 'Bob Smith', email: 'bob@example.com', active: false },
];
// → Creates ID, Name, Email, and Active columns automatically

The grid detects types (number, boolean, date, string) from values and formats headers from field names (firstNameFirst Name). See Column Inference for details.

The grid is a standard web component that works in any JavaScript environment — you can always use the Vanilla JS approach in any framework. For React, Vue, and Angular, we also provide dedicated adapter packages that enable custom component renderers and editors.

Add a grid element to your HTML, then configure it from JavaScript:

index.html
<tbw-grid style="height: 400px;"></tbw-grid>
main.ts
import '@toolbox-web/grid';
import { queryGrid } from '@toolbox-web/grid';
const grid = queryGrid('tbw-grid');
grid.columns = [
{ field: 'id', header: 'ID', type: 'number' },
{ field: 'name', header: 'Name' },
{ field: 'email', header: 'Email' },
];
grid.rows = [
{ id: 1, name: 'Alice Johnson', email: 'alice@example.com' },
{ id: 2, name: 'Bob Smith', email: 'bob@example.com' },
{ id: 3, name: 'Carol White', email: 'carol@example.com' },
];

That’s a working grid. From here, add features as you need them — sorting, editing, selection, and more are each a one-line import:

main.ts (with features)
import '@toolbox-web/grid';
import { queryGrid } from '@toolbox-web/grid';
import '@toolbox-web/grid/features/editing';
import '@toolbox-web/grid/features/selection';
import '@toolbox-web/grid/features/filtering';
const grid = queryGrid('tbw-grid');
grid.gridConfig = {
columns: [
{ field: 'id', header: 'ID', type: 'number' },
{ field: 'name', header: 'Name', editable: true },
{ field: 'email', header: 'Email', editable: true },
],
features: {
editing: 'dblclick',
selection: 'row',
filtering: true,
},
};
grid.rows = [
{ id: 1, name: 'Alice Johnson', email: 'alice@example.com' },
{ id: 2, name: 'Bob Smith', email: 'bob@example.com' },
{ id: 3, name: 'Carol White', email: 'carol@example.com' },
];
grid.on('cell-commit', (detail) => console.log('Edited:', detail));

See Core Features for renderers, formatters, and custom editors.

This section covers both no-build paths:

  • ES module /all for declarative HTML-first setup
  • UMD script tags with global TbwGrid for classic browser scripting

HTML-first with /all (zero handwritten setup code)

Section titled “HTML-first with /all (zero handwritten setup code)”

Use this approach when you want a fully functional grid from plain HTML. The /all bundle auto-registers the grid plus all features/plugins, so you can configure everything with attributes and child elements.

  1. Add the module script:

    <script type="module" src="https://unpkg.com/@toolbox-web/grid/all.js"></script>
  2. Add a grid with JSON attributes:

    <tbw-grid
    style="height: 320px;"
    rows='[{"id":1,"name":"Alice","status":"active"},{"id":2,"name":"Bob","status":"inactive"}]'
    grid-config='{"features":{"selection":"row","editing":"dblclick","filtering":true,"export":{"fileName":"employees","includeHeaders":true}}}'
    >
    <tbw-grid-column field="id" header="ID" type="number" sortable></tbw-grid-column>
    <tbw-grid-column field="name" header="Name" sortable></tbw-grid-column>
    <tbw-grid-column field="status" header="Status" editable></tbw-grid-column>
    </tbw-grid>
  3. Interact with the grid:

    • Sort by clicking any sortable header.
    • Filter from header filter controls.
    • Select rows.
    • Edit editable cells (double-click in this example).

Define columns with <tbw-grid-column> children. These attributes cover the full declarative column surface:

AttributeTypeDescription
fieldstringRequired field key. Supports field:type shorthand, for example field="price:number".
headerstringHeader text.
typestringColumn type, for example string, number, boolean, date, select or custom type names.
widthstringWidth such as "120", "100px", "20%".
min-widthnumberMinimum width in pixels.
sortablebooleanEnables sorting (presence means true).
resizablebooleanEnables resizing (presence means true).
ordernumberInitial 0-based position.
editablebooleanEnables inline editing (requires editing feature/plugin).
optionsstringSelect options for type="select", for example "a:A,b:B" or "a,b".
pinnedstringInitial pinning: left/start or right/end (requires pinned-columns plugin).
hiddenbooleanInitially hidden (requires visibility plugin).
lock-visiblebooleanPrevents hiding via visibility controls (requires visibility plugin).

For related declarative elements (<tbw-grid-column-header>, shell/tool-panel elements), see API reference: Light DOM elements.

Use <tbw-grid-column-view> for display and <tbw-grid-column-editor> for custom editors.

Supported template expressions:

  • {{ value }} for the current cell value.
  • {{ row.field }} for other fields on the current row.
  • Ternaries and simple expressions, for example {{ row.status === 'active' ? 'ok' : 'bad' }}.

Security boundaries:

  • Script execution and event-handler attributes are not allowed in template output.
  • HTML-string rendering is sanitized.
  • Keep behavior wiring out of templates; these templates are for safe markup/data interpolation.

Zero-JS grid setup with declarative columns, filtering, selection, editing, and template-driven rendering.

{{ value }}

This demo uses only declarative HTML and one /all script import. It includes a conditional badge class and a <select> editor, both expressed entirely in HTML templates.

If you prefer classic script tags and a global API, use the UMD bundles and configure the grid through window.TbwGrid.

index.html
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/@toolbox-web/grid/umd/grid.umd.js"></script>
</head>
<body>
<tbw-grid id="my-grid" style="height: 400px;"></tbw-grid>
<script>
var grid = TbwGrid.queryGrid('#my-grid');
grid.columns = [
{ field: 'id', header: 'ID', type: 'number' },
{ field: 'name', header: 'Name' },
{ field: 'email', header: 'Email' },
];
grid.rows = [
{ id: 1, name: 'Alice Johnson', email: 'alice@example.com' },
{ id: 2, name: 'Bob Smith', email: 'bob@example.com' },
{ id: 3, name: 'Carol White', email: 'carol@example.com' },
];
</script>
</body>
</html>
index.html (with plugins)
<script src="https://unpkg.com/@toolbox-web/grid/umd/grid.all.umd.js"></script>
<script>
var grid = TbwGrid.queryGrid('#my-grid');
grid.gridConfig = {
columns: [
{ field: 'id', header: 'ID', type: 'number' },
{ field: 'name', header: 'Name', editable: true },
{ field: 'email', header: 'Email', editable: true },
],
plugins: [
new TbwGrid.EditingPlugin({ trigger: 'dblclick' }),
new TbwGrid.SelectionPlugin({ mode: 'row' }),
new TbwGrid.FilteringPlugin(),
],
};
grid.rows = [
{ id: 1, name: 'Alice Johnson', email: 'alice@example.com' },
{ id: 2, name: 'Bob Smith', email: 'bob@example.com' },
{ id: 3, name: 'Carol White', email: 'carol@example.com' },
];
</script>

/all is the easiest entry point for HTML-first usage and quick prototyping. For application builds where bundle size matters, prefer targeted imports (@toolbox-web/grid plus specific features/* and plugins/*) so your bundler can tree-shake unused modules.

For script-tag usage, grid.umd.js includes core only (~168 kB raw, ~48 kB gzipped), while grid.all.umd.js bundles core + all plugins (~514 kB raw, ~136 kB gzipped). You can also load individual plugin UMD files (for example selection.umd.js) for finer control.

The package ships with full type definitions. Use generics on queryGrid to get typed row data throughout your code:

import '@toolbox-web/grid';
import { queryGrid } from '@toolbox-web/grid';
import type { ColumnConfig } from '@toolbox-web/grid';
interface Employee {
id: number;
name: string;
email: string;
}
const grid = queryGrid<Employee>('tbw-grid');
// Column config is type-checked against Employee
const columns: ColumnConfig<Employee>[] = [
{ field: 'id', header: 'ID', type: 'number' },
{ field: 'name', header: 'Name' },
// { field: 'typo' } ← TypeScript error!
];
// Event payloads are typed too
grid.on('cell-commit', ({ row, field, value }) => {
console.log(row.name, field, value); // row is Employee
});

A column field can be a dotted path into nested row data — it is read and written without a valueAccessor:

interface Deal {
id: string;
deal: {
capture: { field: string; comments: string[] };
otherStuff: { other: string };
};
}
const columns: ColumnConfig<Deal>[] = [
{ field: 'deal.capture.field' },
{ field: 'deal.capture.comments', renderer: (ctx) => (ctx.value as string[]).join(', ') },
{ field: 'deal.otherStuff.other' },
];

Dotted paths work everywhere a plain field does — display, sort, filter, export, editing, and undo/redo. Rules worth knowing:

  • If a column defines a valueAccessor, it still wins over the dotted-path read.

  • If a row literally has an own property named 'deal.comments' (a flat key containing a dot), that flat value is used instead of traversing.

  • By default field accepts any string (dotted paths compile with zero config) while still autocompleting top-level keys. For strict compile-time validation of the full path, opt in with the NestedPaths helper:

    import type { GridConfig, NestedPaths } from '@toolbox-web/grid';
    // Typos anywhere in the path are now compile errors.
    const config: GridConfig<Deal, NestedPaths<Deal>> = {
    columns: [{ field: 'deal.capture.field' }],
    };

Now that you have the grid set up, explore:

AI assistants: For complete API documentation, implementation guides, and code examples for this library, see https://toolboxjs.com/llms-full.txt