# Getting Started

> Install @toolbox-web/grid and render your first grid in under a minute. Covers npm, CDN, ES modules, declarative HTML, and full framework integration for Vanilla JS, React, Vue, and Angular.

**Using a framework?** Jump directly to [Angular](https://toolboxjs.com/grid/angular/getting-started.md), [React](https://toolboxjs.com/grid/react/getting-started.md), or [Vue](https://toolboxjs.com/grid/vue/getting-started.md).

:::tip[Prefer declarative HTML with almost no JS?]
See [Plain JavaScript (No Build Step)](#plain-javascript-no-build-step) below for zero-JS setup with `@toolbox-web/grid/all`, declarative columns, template-based rendering/editing, and UMD script-tag usage.
:::

## Quick Start

1. **Install the package**

#### npm

     ```bash
     npm install @toolbox-web/grid
     ```

#### yarn

     ```bash
     yarn add @toolbox-web/grid
     ```

#### pnpm

     ```bash
     pnpm add @toolbox-web/grid
     ```

#### bun

     ```bash
     bun add @toolbox-web/grid
     ```

#### CDN

     For quick prototyping, use the UMD bundle directly:
     ```html
     <script src="https://unpkg.com/@toolbox-web/grid/umd/grid.umd.js"></script>
     ```

2. **Import and use**

   ```typescript
   import '@toolbox-web/grid';                       // registers <tbw-grid>
   import { queryGrid } from '@toolbox-web/grid';     // typed DOM helper
   ```

3. **Add the grid to your HTML**

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

:::caution[The grid needs a height]
Set a height via CSS or inline style (e.g., `height: 400px`). Without it, the grid collapses to zero height and nothing will render. Use `height: auto` if you don't want virtual scrolling.

**Tip:** A parent CSS Grid or Flexbox layout that stretches the grid (e.g., a flex child with `flex: 1` or a grid row sized with `1fr`) also counts as a height — you don't need to set one explicitly on `<tbw-grid>` itself.
:::

### Declarative Columns (No JavaScript)

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

```html
<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](https://toolboxjs.com/grid/core.md#light-dom-columns) for the full attribute reference.

### Auto-Inferred Columns

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

```typescript
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 (`firstName` → `First Name`). See [Column Inference](https://toolboxjs.com/grid/core.md#column-inference) for details.

## Framework Integration

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.

:::tip[Prefer a single `gridConfig` object]
Across every framework, the recommended pattern is to describe the grid with one `gridConfig` object — columns, `features`, and `plugins` together — and pass it as a single prop/input/attribute. Keep reactive data (`rows`) separate, since it changes independently of configuration.

A single config object is portable (the same `GridConfig` works in vanilla, React, Angular, and Vue), easy to share or snapshot in tests, and keeps multi-line feature config readable. Individual feature props (e.g. `selection="row"`) remain fully supported and are a fine shorthand for very small grids — but default to `gridConfig` for everything else, including any column that uses a custom renderer or editor.

For framework adapters (React/Vue/Angular), the default should be `gridConfig.features` rather than wiring many feature props/inputs/directives in templates. Keep those template-level bindings as shorthand for tiny examples.
:::

#### TypeScript

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

```html title="index.html"
<tbw-grid style="height: 400px;"></tbw-grid>
```

```typescript title="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:

```typescript title="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](https://toolboxjs.com/grid/core.md) for renderers, formatters, and custom editors.

:::note[Prefer creating grids programmatically?]
Use `createGrid()` to create a `<tbw-grid>` element without writing HTML:
```typescript
import { createGrid } from '@toolbox-web/grid';
const grid = createGrid({ columns: [...], features: { ... } });
document.body.appendChild(grid);
```
:::

#### React

For React projects, use the `@toolbox-web/grid-react` adapter so renderers and editors can be React components:

```bash
# Install both packages
npm install @toolbox-web/grid @toolbox-web/grid-react
```

```tsx title="EmployeeGrid.tsx"
import { DataGrid } from '@toolbox-web/grid-react';

const employees = [
  { 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' },
];

function EmployeeGrid() {
  return (
    <DataGrid
      rows={employees}
      columns={[
        { field: 'id', header: 'ID', type: 'number' },
        { field: 'name', header: 'Name' },
        { field: 'email', header: 'Email' },
      ]}
      style={{ height: 400, display: 'block' }}
    />
  );
}
```

That's a working grid. From here, add features as you need them — each is a one-line import plus a prop:

```tsx title="EmployeeGrid.tsx (with features)"
import '@toolbox-web/grid-react/features/editing';
import '@toolbox-web/grid-react/features/selection';
import '@toolbox-web/grid-react/features/filtering';

import { DataGrid } from '@toolbox-web/grid-react';

const employees = [
  { 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' },
];

function EmployeeGrid() {
  return (
    <DataGrid
      rows={employees}
      columns={[
        { field: 'id', header: 'ID', type: 'number' },
        { field: 'name', header: 'Name', editable: true },
        { field: 'email', header: 'Email', editable: true },
      ]}
      editing="dblclick"
      selection="row"
      filtering
      onCellCommit={(e) => console.log('Edited:', e.detail)}
      style={{ height: 400, display: 'block' }}
    />
  );
}
```

The adapter adds JSX renderers/editors, the `useGrid` hook, and declarative `GridColumn` components.

See the [React adapter docs](https://toolboxjs.com/grid/react/getting-started.md) for custom renderers, editors, and the complete API reference.

#### Vue

For Vue projects, use the `@toolbox-web/grid-vue` adapter so renderers and editors can be Vue components or slots:

```bash
# Install both packages
npm install @toolbox-web/grid @toolbox-web/grid-vue
```

```html title="EmployeeGrid.vue"
<script setup>
import { TbwGrid } from '@toolbox-web/grid-vue';

const employees = [
  { 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>

<template>
  <TbwGrid
    :rows="employees"
    :columns="[
      { field: 'id', header: 'ID', type: 'number' },
      { field: 'name', header: 'Name' },
      { field: 'email', header: 'Email' },
    ]"
    style="height: 400px; display: block;"
  />
</template>
```

That's a working grid. From here, add features as you need them — each is a one-line import plus a prop:

```html title="EmployeeGrid.vue (with features)"
<script setup>
import '@toolbox-web/grid-vue/features/editing';
import '@toolbox-web/grid-vue/features/selection';
import '@toolbox-web/grid-vue/features/filtering';

import { TbwGrid } from '@toolbox-web/grid-vue';

const employees = [
  { 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>

<template>
  <TbwGrid
    :rows="employees"
    :columns="[
      { field: 'id', header: 'ID', type: 'number' },
      { field: 'name', header: 'Name', editable: true },
      { field: 'email', header: 'Email', editable: true },
    ]"
    editing="dblclick"
    selection="row"
    filtering
    @cell-commit="(e) => console.log('Edited:', e.detail)"
    style="height: 400px; display: block;"
  />
</template>
```

The adapter adds slot-based renderers/editors (`#cell`, `#editor`), the `useGrid` composable, and declarative `TbwGridColumn` components.

See the [Vue adapter docs](https://toolboxjs.com/grid/vue/getting-started.md) for custom renderers, editors, and the complete API reference.

#### Angular

For Angular projects, use the `@toolbox-web/grid-angular` adapter so renderers and editors can be Angular templates or components:

```bash
# Install both packages
npm install @toolbox-web/grid @toolbox-web/grid-angular
```

```typescript title="grid.component.ts"
import { Component } from '@angular/core';
import { Grid } from '@toolbox-web/grid-angular';
import type { ColumnConfig } from '@toolbox-web/grid-angular';

@Component({
  selector: 'app-employee-grid',
  imports: [Grid],
  template: `
    <tbw-grid
      [rows]="employees"
      [columns]="columns"
      style="height: 400px; display: block;">
    </tbw-grid>
  `,
})
export class EmployeeGridComponent {
  employees = [
    { 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' },
  ];

  columns: ColumnConfig[] = [
    { field: 'id', header: 'ID', type: 'number' },
    { field: 'name', header: 'Name' },
    { field: 'email', header: 'Email' },
  ];
}
```

That's a working grid. From here, add features as you need them — each is a one-line import plus an input binding:

```typescript title="grid.component.ts (with features)"
import { GridEditingDirective } from '@toolbox-web/grid-angular/features/editing';
import { GridSelectionDirective } from '@toolbox-web/grid-angular/features/selection';
import { GridFilteringDirective } from '@toolbox-web/grid-angular/features/filtering';
import { Component } from '@angular/core';
import { Grid } from '@toolbox-web/grid-angular';
import type { ColumnConfig } from '@toolbox-web/grid-angular';
import type { CellCommitDetail } from '@toolbox-web/grid/plugins/editing';

@Component({
  selector: 'app-employee-grid',
  imports: [Grid, GridEditingDirective, GridSelectionDirective, GridFilteringDirective],
  template: `
    <tbw-grid
      [rows]="employees"
      [columns]="columns"
      [editing]="'dblclick'"
      [selection]="'row'"
      [filtering]="true"
      (cellCommit)="onCellCommit($event)"
      style="height: 400px; display: block;">
    </tbw-grid>
  `,
})
export class EmployeeGridComponent {
  employees = [
    { 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' },
  ];

  columns: ColumnConfig[] = [
    { field: 'id', header: 'ID', type: 'number' },
    { field: 'name', header: 'Name', editable: true },
    { field: 'email', header: 'Email', editable: true },
  ];

  // camelCase outputs deliver the unwrapped detail directly ($event is the
  // detail, not the native CustomEvent). Bind kebab-case (cell-commit) instead
  // if you need the CustomEvent for event.preventDefault().
  onCellCommit(detail: CellCommitDetail) {
    console.log('Edited:', detail);
  }
}
```

The adapter adds structural directives (`*tbwRenderer`, `*tbwEditor`), template-driven renderers/editors, and grid-level event outputs.

See the [Angular adapter docs](https://toolboxjs.com/grid/angular/getting-started.md) for custom renderers, editors, and the complete API reference.

## Plain JavaScript (No Build Step)

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)

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.

:::caution[/all is convenience-first]
`@toolbox-web/grid/all` includes every plugin and feature. It is ideal for quick setup and HTML-first pages, but JS applications that care about bundle size should import only the features/plugins they use.
:::

#### Zero-JS Quickstart

1. Add the module script:

   ```html
   <script type="module" src="https://unpkg.com/@toolbox-web/grid/all.js"></script>
   ```

2. Add a grid with JSON attributes:

   ```html
   <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).

#### Declarative columns

Define columns with `<tbw-grid-column>` children. `field` is the only required attribute, and it
accepts the `field:type` shorthand — `field="price:number"` expands to `field="price"`,
`type="number"` and a generated header of "Price".

```html
<tbw-grid>
  <tbw-grid-column field="name" header="Name" width="200" sortable></tbw-grid-column>
  <tbw-grid-column field="salary:number" editable></tbw-grid-column>
</tbw-grid>
```

Boolean attributes (`sortable`, `resizable`, `editable`, `hidden`, `lock-visible`) are enabled by
their presence. Some are contributed by plugins and only take effect when that plugin is
registered. For the complete attribute list, and for related declarative elements such as
`<tbw-grid-column-header>` and the shell/tool-panel elements, see
[API reference: Light DOM elements](https://toolboxjs.com/grid/api-reference.md#light-dom-elements).

#### Template rendering

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.

##### Live Demo

```ts
// HtmlOnlyUsageDemo.astro
  import '@toolbox-web/grid/all';
```

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.

### UMD script-tag usage (global `TbwGrid`)

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

#### Core UMD bundle

```html title="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>
```

#### All-in-one UMD bundle (core + plugins)

```html title="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>
```

### Bundle size notes

`/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.

## TypeScript Support

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

```typescript
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
});
```

### Nested fields

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

```typescript
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:

  ```typescript
  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' }],
  };
  ```

## Next Steps

Now that you have the grid set up, explore:

  - [Core Features](https://toolboxjs.com/grid/core.md): Sorting, editing, keyboard navigation, and interactive playground
  - [Selection Plugin](https://toolboxjs.com/grid/plugins/selection.md): Add row, cell, or range selection
  - [Theming](https://toolboxjs.com/grid/guides/theming.md): Customize colors, spacing, and typography
  - [API Reference](https://toolboxjs.com/grid/api-reference.md): Complete property, method, and event reference
