The Grid API
Controlling the grid from your own code
The Grid API is your remote control for the grid. It has 50+ methods to read and change data, columns, sorting, filters, selection, editing, pagination, scrolling, and export — all from your own code.
"API" = Application Programming Interface. In plain terms it's the agreed set of commands one piece of code offers to another. The Grid API is just an object full of methods (
api.setPage(2),api.exportCSV(), …). You don't reach inside the grid's internals; you call these published methods and the grid does the work.
Two ways to interact with the grid, and when to use each:
- The API (this chapter) — for doing things on demand: a button that exports CSV, code that jumps to page 2, a "select all" action. You call it.
- Reactive state composables (end of this chapter) — for displaying live grid state in your own UI: "3 of 100 selected". They push updates to you.
Reach for the API when an action happens; reach for the composables when you need to mirror grid state on screen.
How to get the API
You receive it in the onReady event. The common pattern is to stash it in a ref so the rest of your component can use it:
<script setup lang="ts">
import { ref } from 'vue'
import { createGrid, Grid } from '@elitegrid/vue'
import type { GridAPI } from '@elitegrid/vue'
const api = ref<GridAPI<User> | null>(null)
const grid = createGrid<User>({
columns,
data,
events: {
onReady: (a) => {
api.value = a
},
},
})
</script>
<template>
<div>
<button :disabled="!api" @click="api?.exportCSV()">
Export CSV
</button>
<div style="height: 500px">
<Grid :grid="grid" />
</div>
</div>
</template>
Because
<script setup>only runs once, you can registeronReadydirectly insidecreateGrid— no equivalent of React'supdateEvents-to-avoid-staleness dance is needed here (see Chapter 11). You can also just call API methods directly fromonReadyif you don't need them in your template.
The complete API reference
Data
api.setData(rows) // replace all rows
api.getData() // → TData[] (the raw, unfiltered rows)
api.getDisplayedRows() // → TData[] (current page, after filter+sort)
api.refreshData() // re-run the pipeline / re-fetch from dataSource
api.addRow(row, index?) // add a row (optionally at an index)
api.updateRow(id, changes) // patch a row by ID
api.deleteRow(id) // delete one row
api.deleteRows(ids) // delete many rows in a single pass (fast)
getData()vsgetDisplayedRows()— the "pipeline". Internally the grid runs your rows through a pipeline: raw data → filter → sort → paginate → what's on screen.getData()returns the rows from the start of that pipeline (everything, untouched).getDisplayedRows()returns the rows at the end — already filtered, sorted, and limited to the current page, in the exact order shown. UsegetData()for "all my records"; usegetDisplayedRows()for "what the user is actually looking at right now".
updateRow(id, changes)— what "patch" means. You pass only the fields that changed, e.g.api.updateRow('42', { salary: 90000 }), and the grid merges them into the existing row. You don't have to send the whole row back.
Columns
api.setColumnVisible(id, visible)
api.setColumnWidth(id, width)
api.setColumnPinned(id, 'left' | 'right' | null)
api.moveColumn(id, toIndex)
api.getAllColumns() // → ColumnDef[] (everything you passed in)
api.getVisibleColumns() // → ColumnDef[] (currently visible)
api.getColumnState() // → ColumnState[] (widths, order, pinning, visibility)
api.applyColumnState(state) // restore a saved layout
Sort
api.setSortModel([{ columnId: 'name', direction: 'asc' }])
api.getSortModel()
api.clearSort()
Filter
api.setFilterModel(model)
api.getFilterModel()
api.setColumnFilter(columnId, filter)
api.clearColumnFilter(columnId)
api.clearFilters()
Selection
api.selectRow(id)
api.deselectRow(id)
api.toggleRow(id)
api.selectAll()
api.deselectAll()
api.isRowSelected(id) // → boolean
api.getSelectedRows() // → TData[]
api.getSelectedIds() // → Set<string>
Editing
api.startEditing(rowId, columnId)
api.stopEditing(save?) // true = save, false = discard
api.isEditing() // → boolean
api.getEditingCell() // → { rowId, columnId, rowIndex, columnIndex } | null
Pagination
api.setPage(page)
api.setPageSize(size)
api.nextPage()
api.previousPage()
api.firstPage()
api.lastPage()
api.getPaginationState() // → PaginationState
Scrolling
api.scrollToRow(rowId)
api.scrollToColumn(columnId)
api.scrollToCell(rowId, columnId)
Export
api.exportCSV(options?) // see Chapter 10
Lifecycle
api.destroy() // tear down the engine (rarely needed by hand)
Reactive state composables (advanced)
What does "reactive" mean here? A reactive value automatically updates your template when it changes — you bind it once and Vue keeps it up to date, rather than you polling for changes. The API's
get…methods give you a snapshot (correct only at the instant you call them); these composables give you aRefthat stays correct.
Most apps only need createGrid + <Grid> + the API. But if you want to read grid state reactively inside your own components (e.g. show "3 of 100 rows selected" in your own toolbar), the adapter exports a set of composables — each returns a read-only Ref:
<script setup lang="ts">
import { usePaginationState } from '@elitegrid/vue'
import type { GridInstance } from '@elitegrid/vue'
const props = defineProps<{ grid: GridInstance<User> }>()
const pagination = usePaginationState(props.grid)
</script>
<template>
<span>{{ pagination.totalRows }} rows</span>
</template>
These re-render your component whenever that slice of grid state changes. The main ones you'll reach for:
| Composable | Returns state about |
|---|---|
useViewportState(grid) |
Which rows/columns are currently rendered, scroll position |
useColumnsState(grid) |
Column widths, order, visibility, pinning |
usePaginationState(grid) |
Current page, page size, total rows/pages |
useSortedState(grid) |
The current sort model |
useFilteredState(grid) |
The current filter model and match count |
useRawState(grid) |
The unfiltered row data and loading/error state |
useSelectionState(grid) |
Selected IDs, count, select-all state |
useEditState(grid) |
Whether a cell is editing, its value, validation state |
useFocusState(grid) |
The currently focused cell |
A few smaller, cell-scoped composables are also available for building custom cell renderers: useCellSelected(grid, rowId), useCellFocused(grid, rowId, columnId), and useCellEditing(grid, rowId, columnId).
Cleaning up
If you created the grid with plain createGrid(), it lives until you explicitly destroy it — usually fine for a single grid that lives for the whole app. If the component holding the grid can be mounted and unmounted repeatedly (a route, a modal, a tab), either destroy it yourself:
import { onBeforeUnmount } from 'vue'
onBeforeUnmount(() => grid.kernel.destroy())
…or use useCreateGrid() instead of createGrid() when you first build it, which registers that same cleanup for you automatically (see Chapter 01):
import { useCreateGrid } from '@elitegrid/vue'
const grid = useCreateGrid<User>({ columns, data }) // destroyed on unmount, for free
Next: 13 · Accessibility