Skip to content

Getting Started ​

Installation ​

bash
npm install @dynamicforms/vue-grid

In your main.ts:

typescript
import { DynamicFormsVueGrid } from '@dynamicforms/vue-grid';
import '@dynamicforms/vue-grid/styles.css';

const app = createApp(MyApp);
app.use(router);
app.use(vuetify);

// makes <DfGrid> available globally
app.use(DynamicFormsVueGrid, { registerComponents: true });
// skip global component registration; still registers v-longpress
// app.use(DynamicFormsVueGrid);

If you prefer to register <DfGrid> locally in individual components:

typescript
import { DfGrid } from '@dynamicforms/vue-grid';

See DynamicFormsVueGridOptions for the full set of install options.

Basic Usage ​

vue
<template>
  <df-grid
    :columns="columns"
    :records="records"
    key-field="id"
  />
</template>

<script setup lang="ts">
import { createColumn, DfGrid } from '@dynamicforms/vue-grid';

const columns = [
  createColumn('id',    'ID',    'int'),
  createColumn('name',  'Name',  'plain', { sortable: true }),
  createColumn('email', 'Email', 'email'),
];

const records = [
  { id: 1, name: 'Alice', email: 'alice@example.com' },
  { id: 2, name: 'Bob',   email: 'bob@example.com' },
];
</script>

<style>
.df-record-grid {
  display:               grid;
  grid-template-columns: minmax(2em, 4em) 1fr 1fr;
  gap:                   0.25em;
}
</style>

The <style> block above is required, not optional polish

The template and script alone render every cell stacked on its own line, one per row of text, not a table — the grid has no fallback layout of its own. .df-record-grid has to be display: grid with a track per column before anything lines up. See Card layout CSS below for why.

<df-grid> needs a definite height from somewhere

Rows are virtualized against the grid's own scroll viewport, so <df-grid> (or an ancestor of it) needs a bounded height — a fixed height, a vh/% value backed by a sized ancestor, or being a flex/grid item that fills available space (flex: 1 1 auto; min-height: 0, say). Leave every ancestor unconstrained and the body scroller collapses to zero height instead, with nothing left to window rows against; <df-grid> logs a console warning when this happens, but the fix is still on your side of the boundary — give it height.

Card layout CSS ​

The grid's own layout comes from your own stylesheet, as set above — make .df-record-grid a grid and give it a base track list, one track per column; the grid reads the body's actual (natively-resolved) widths and republishes them onto the header for you. .df-record-grid is the marker every place that lays out a record's fields carries — the real scrolling body, the header, and the filter row alike — so this one declaration covers all three, instead of just the body. Each cell carries its column's fieldName as a CSS class, so you can target individual columns by name once the base grid is in place:

css
.df-grid.cell.id { text-align: right; }

See Card layout CSS for how column widths are measured and published, and Grid structure for the full section layout diagram.

Translation ​

The grid draws a small number of English strings of its own, each under a key naming what it says rather than its English text. The library ships no translations and selects no locale: the application passes its translation function to translateStrings once, with the namespace that holds the grid's keys in its translations.

The authoritative list is src/table/translations.ts - the object passed to createTranslatable there is the whole catalogue:

KeyEnglish defaultWhere it appears
LoadingLoading…Summary bar, while loading is true
NoDataNo dataSummary bar, when records is empty
FilterColumnFilter {column}...Filter row's default placeholder, when a filterable column has none of its own
CancelSelectionModeCancel selection modeSelection status bar's cancel icon tooltip
InvertSelectionInvert selectionSelection status bar's invert icon tooltip
SelectionCountSelected{count} items selectedSelection status bar, in 'selection' mode
SelectionCountExcluded{count} items excludedSelection status bar, in 'exclusion' mode
ActiveFiltersActive filters: {count}Status bar's default statusBar slot content
RecordCount{count} recordsStatus bar's default statusBar slot content, when the total is unknown
RecordCountOfTotal{count} of {total} recordsStatus bar's default statusBar slot content
NullValuenullA cell's content when its value is null/undefined and no nullHandler says otherwise

With vue-i18n:

typescript
import { formatParams } from '@dynamicforms/translatable';
import { translateStrings } from '@dynamicforms/vue-grid';

const { t, n } = i18n.global;
// formats `{count}` for the locale before t substitutes it
translateStrings(formatParams(t, (value) => (typeof value === 'number' ? n(value) : value)), 'grid');
json
{ "grid": { "NoData": "Ni podatkov", "ActiveFilters": "Aktivni filtri: {count}" } }
  • A key is looked up as grid.<Key>; without a namespace, as <Key>.
  • The grid passes each placeholder's value to the translation function, which substitutes it. A translation uses the placeholder names of the English default.
  • A key the translation function returns unchanged has no translation and reads as the English default.
  • The grid calls the translation function on every render, so a grid on screen follows a locale switch of vue-i18n's t without another translateStrings call. A translation function over non-reactive translations needs another translateStrings call after they change.

translate(key, params?) returns the current text of one of these keys, for an application drawing its own status bar or summary with the grid's strings.

The @dynamicforms/translatable readme describes the translation function, the resolution order and a translation function written without an i18n library.

Next steps ​

The example above covers a plain, read-only grid. From here:

  • Sorting — sortable: true on any column
  • Filtering — filterable: true on a column, :show-filter-row="true" on the grid
  • Responsive layouts — multiple column sets that switch automatically with container width
  • Row selection — shift+click, long-press, and #groupActions batch actions, built in

The Cookbook has copy-pasteable recipes for common tasks beyond a plain data column — clickable action icons, a dedicated selection checkbox column, responsive card layouts, and more.

Released under the MIT License.