# av-grid API reference
A dependency-free, framework-agnostic virtualized data grid that renders straight to the DOM.
Built for 100,000+ rows with no lag while scrolling, selecting or editing.
This page is the complete public surface. It is written to be read once, mid-task, to answer one
question — so it is exhaustive and skimmable, and every entry carries the snippet you would
actually type. Runnable standalone files live in [`../examples/`](../examples/).
> **av-grid is not AG Grid.** The names differ by one character and nothing else does: av-grid
> shares no API, no options and no lineage with it. There is no `columnDefs`, no `rowData`, no
> `createGrid`, no module registration. If you are filling a gap from memory, fill it from this
> page — a half-remembered AG Grid call is *plausible and wrong*, which is the expensive kind of
> mistake. The UMD global is `AVGrid`, capital V.
**Contents**
- [Install and the minimum call](#install-and-the-minimum-call)
- [The naming decision](#the-naming-decision)
- [`AVGrid` statics](#avgrid-statics)
- [Options](#options)
- [Columns](#columns)
- [What is inferred](#what-is-inferred)
- [Instance methods](#instance-methods)
- [Callbacks, at a glance](#callbacks-at-a-glance)
- [Filtering](#filtering)
- [The filter bar](#the-filter-bar)
- [The context menu](#the-context-menu)
- [Keyboard reference](#keyboard-reference)
- [Theming](#theming)
- [DOM contract](#dom-contract)
- [Primitives](#primitives)
- [Helpers](#helpers)
- [The engine](#the-engine)
- [Errors and warnings](#errors-and-warnings)
- [Performance notes](#performance-notes)
---
## Install and the minimum call
```html
```
That is the whole minimum call. Columns, header labels, widths, data types, alignment and row
keys are all inferred from the rows — see [What is inferred](#what-is-inferred).
**The host needs a height.** The grid measures its own root to decide what is on screen, so that
height has to be *definite*. A host with a height (`height: 400px`, a flex child, `position:
absolute`) gets a grid that fills it; a host with no height at all gets a pixel fallback, and the
grid re-measures once on the next frame in case the page simply had not laid out yet. If a grid
renders blank, `grid.getState().viewport.width` is the first thing to read — `0` is the answer to
the commonest integration failure.
**Builds.** `dist/av-grid.js` (ESM), `dist/av-grid.umd.cjs` (UMD, global `AVGrid`),
`dist/index.d.ts` (types), `dist/av-grid.css` (the stylesheet, if you would rather link it than
let the grid inject it).
```html
```
The stylesheet is injected into the document on first use and shared by every grid in it. Pass
`injectStyles: false` and link `av-grid.css` yourself if you would rather control it.
---
## The naming decision
**The vocabulary is `key` / `name`, and there are no aliases.**
```js
columns: [{ key: "score", name: "Score" }] // ✅
columns: [{ field: "score", title: "Score" }] // ❌ — not accepted, not aliased
```
Why, since Tabulator's `field` / `title` is at least as familiar:
- **`key` is already the property name.** It is what `row[column.key]` reads, what a filter names
in `columnKey`, what `onEdit` reports, and what `deleteColumns()` takes. Calling the same string
`field` in the column and `columnKey` everywhere else would be two words for one thing.
- **The reference uses it**, and the port's models are kept close to the reference so behaviour can
be diffed against it.
- **`name` beats `title`** because `title` is an HTML attribute with a different meaning (the
tooltip), and a column literal carrying both would read as a contradiction.
- **No aliases, deliberately.** Two ways to spell one thing is worse than either alone: examples
drift between them and generated code becomes inconsistent. So `field` and `title` are silently
ignored rather than accepted, and `validateColumns` raises on a column with no `key` at all.
The reference's misspellings are **not** carried over. Type the correct spelling:
| Reference | Here |
|---|---|
| `haderRenderer` | `headerRender` |
| `cellRenderer` + `cellFormater` | `render` (one hook) |
| `editFormater` | `editor` (a `CellEditor` factory, not a renderer — see [`editor`](#editor--a-custom-cell-editor)) |
| `editRender` | `editor` — this library's own earlier name for the same field, removed because it could not work: it was handed a `CellContext`, so whatever it drew had no way to record a value, commit it or cancel |
| `resizible` | `resizable` |
| `dataAlignment` | `align` |
| `TSortColumn`, `TFilter`, … | `SortColumn`, `Filter`, … (no `T` prefix) |
One flat options object, no required call order: anything you can pass to `create()` you can pass
to `setOptions()` later, and the two run the same code.
---
## `AVGrid` statics
### `AVGrid.create(container, options)`
```js
const grid = AVGrid.create("#host", { rows }); // CSS selector
const grid = AVGrid.create(document.body, { rows }); // or an element
```
`container` is an element or a selector. `options.rows` is the only required option. Returns an
`AVGrid` instance. Throws [`AVGridError`](#errors-and-warnings) on input the grid cannot use.
> **Writing React?** Read [`react-api.md`](react-api.md) instead — the same grid as a
> component, with everything on this page available as props. This page stays framework-free.
### `AVGrid.createFilterBar(container, { grid, className?, name? })`
Mount a filter bar somewhere other than directly above the grid. See
[The filter bar](#the-filter-bar).
### `AVGrid.version`
The library version string. Also exported as `version` from the package root, and reported by
`getState().version`.
### Instance properties
| Property | What it is |
|---|---|
| `grid.element` | The grid's root element. Style it, or read `data-*` off its cells in a test. |
| `grid.model` | The model hub — every sub-model hangs off it. Public so a host can reach past the façade. |
| `grid.render` | The virtualization engine instance, including `grid.render.stats`. |
---
## Options
Every option is optional except `rows`. Everything here can also be passed to
`grid.setOptions({ … })` at any time.
### Data
| Option | Type | Default | Notes |
|---|---|---|---|
| `rows` | `readonly R[]` | — | **Required.** The rows to display. |
| `columns` | `Column[]` | inferred | See [Columns](#columns). |
| `getRowKey` | `(row: R) => string` | inferred | A stable row identity. Selection, focus and editing all address rows by it, so it survives sorting and filtering. |
```js
AVGrid.create(el, {
rows,
getRowKey: (row) => row.orderId,
});
```
### Row selection
| Option | Type | Default | Notes |
|---|---|---|---|
| `selectColumn` | `boolean` | `false` | The checkbox column, pinned left. It is the grid's own: it does not appear in `getColumns()` and does not survive into `setColumns()`. |
| `selected` | `readonly string[]` | `[]` | Initially selected rows, **by row key**. |
| `onSelectionChange` | `(keys: string[]) => void` | — | The checkbox selection changed. Call `getSelectedRows()` for the objects — that is O(rows) and so is not done for you. |
| `focus` | `CellFocus \| null` | `null` | The focused cell and the range around it. Keys alone are enough; `selection` may be omitted for a single cell. The same value `onFocusChange` reports, and safe to hand straight back — see [Focus and range selection](#focus-and-range-selection). |
```js
AVGrid.create(el, {
rows,
selectColumn: true,
selected: ["3", "7"],
onSelectionChange: (keys) => console.log(keys.length, "selected"),
});
```
Row selection (checkboxes) and cell range selection are two different things a grid can have at
once — `getSelected()` for the first, `getSelection()` for the second.
### Editing
| Option | Type | Default | Notes |
|---|---|---|---|
| `editable` | `boolean` | `false` | Let the user edit cells in place. |
| `onEdit` | `(e: CellEditEvent) => void \| boolean` | — | Fires once per committed cell, **before** the write. Return `false` to reject it. |
| `onInvalidEdit` | `(e: InvalidEditEvent) => void` | — | The value could not be coerced to the column's type. Default is to do nothing — a library should not beep uninvited. |
```js
AVGrid.create(el, {
rows,
editable: true,
onEdit: (e) => save(e.rowKey, e.columnKey, e.value),
});
```
**The grid writes the value into the row object** (`row[column.key] = value`) and then calls
`onEdit`. Return `false` to keep the write from happening and own the update yourself.
How an editor opens:
| Gesture | What happens |
|---|---|
| Click a cell that already has the focus | Opens, **caret where the click landed**, nothing selected. A cold cell therefore takes two clicks and a focused one takes a single click. |
| Double-click | Opens the same way. |
| `Enter` / `F2` / `grid.startEdit()` | Opens with the **whole value selected**, so the next keystroke replaces it. |
| Type a printable character | Opens with that character as the value, caret after it. |
| `Escape` | Cancels. |
| `Enter`, `Tab`, `ArrowUp`, `ArrowDown`, blur | Commits. `Tab` and the vertical arrows then move the focus; the horizontal arrows stay in the text, moving the caret. |
Boolean columns have no text editor: `Space`, `Enter` or a double-click toggles them across the
whole selection, and an editable boolean cell carries a checkbox that toggles on the first click
(only the box toggles — the cell around it just selects). `Delete` clears every editable cell in
the selection. A column with `options` opens the library's own themed dropdown rather than a
native `