gp-grid-logo

Vue migration to version 1.0

Migrate the Vue gp-grid wrapper from 0.23.x to 1.0 with before-and-after examples for public exports, callback props, column state, refs, writes, and refresh.

This guide is for Vue.

Using another framework? Select the correct guide.

This guide covers migrating @gp-grid/vue from 0.23.x to 1.0. It focuses on the component integration; use the shared core migration reference for custom adapters and the complete imperative API mapping.

Upgrade packages

bun add @gp-grid/vue@^1.0.0

Upgrade any other installed @gp-grid/* packages together. Keep importing the stylesheet once:

import "@gp-grid/vue/dist/styles.css";

Upgrade Vue to ^3.5.0; the component uses useId. Import the component as GpGrid or the package default.

The package no longer exports component internals: useInputHandler, useAutoScroll, useFillHandle, useFilterPopup, useFilterConditions, useGridState, createInitialState, renderCell, renderEditCell, renderHeader, getCellValue, or their option/result types.

Shared core helpers and types are also no longer re-exported here: buildCellClasses, isCellActive, isCellEditing, isCellInFillPreview, isCellSelected, calculateColumnPositions, findColumnAtX, getTotalWidth, isRowVisible, FilterPopupState, HeaderData, PointerEventData, and SelectionState. Import these from @gp-grid/core instead. The public useGpGrid and useGridData composables remain available.

Before
import { isCellSelected } from "@gp-grid/vue";
After
import { isCellSelected } from "@gp-grid/core";

Events carry identity

Interaction callbacks now receive one object with stable identity and named view indices. There is no compatibility adapter for positional arguments or the old payloads.

Callbacks are props. Bind them with :on-column-resized, :on-column-moved, and :on-row-drag-end.

Before
function handleColumnResized(colIndex: number, newWidth: number) {
  persistWidth(colIndex, newWidth);
}
function handleColumnMoved(fromIndex: number, toIndex: number) {
  persistOrder(fromIndex, toIndex);
}
function handleRowDragEnd(sourceIndex: number, targetIndex: number) {
  dataSource.moveRow(sourceIndex, targetIndex);
}
After
<script setup lang="ts">
import type { ColumnResizedEvent, ColumnMovedEvent, RowDragEndEvent } from "@gp-grid/vue";

function handleColumnResized({ columnId, width, viewIndex }: ColumnResizedEvent) {
  persistWidth(columnId, width, viewIndex);
}
function handleColumnMoved({ columnId, fromViewIndex, toViewIndex }: ColumnMovedEvent) {
  persistOrder(columnId, fromViewIndex, toViewIndex);
}
function handleRowDragEnd({ fromViewIndex, toViewIndex }: RowDragEndEvent) {
  dataSource.moveRow(fromViewIndex, toViewIndex);
}
</script>

<template>
  <GpGrid
    :columns="columns"
    :data-source="dataSource"
    :row-height="36"
    :on-column-resized="handleColumnResized"
    :on-column-moved="handleColumnMoved"
    :on-row-drag-end="handleRowDragEnd"
  />
</template>

RowDragEndEvent also includes rowId. Column indices describe the resolved layout; persist state by identity. CellValueChangedEvent now includes columnId. A resize with no committed change fires no event.

Column definitions and column state

Definitions are immutable inputs. The core owns live order, widths, visibility, and pins by colId ?? field. Remove code that depends on the grid mutating a definition or requires you to reorder the columns array after a drag. A column-move callback is a notification of the committed move.

Use the controlled columnState input for explicit overrides:

<GpGrid :columns="columns" :column-state="[{ columnId: 'city', width: 240 }]" :row-data="data" :row-height="36" />

Replacing columns keeps the core instance and retains state, sorting, and filtering for surviving column ids. Removed ids lose their state. Definition changes apply only where no user override exists.

To save state, read core.columns.getState(). To restore a saved snapshot after further edits, call core.columns.resetState() before core.columns.setState(savedState). width is an explicit override; resolvedWidth is output-only and is zero while hidden. Invalid widths fall back to 50 px.

Imperative API access

A component template ref still exposes core.

Before
gridRef.value?.core?.setSort("name", "asc");
gridRef.value?.core?.startEdit(0, 1);
After
gridRef.value?.core?.sortFilter.setSort("name", "asc");
gridRef.value?.core?.edit.start(0, 1);

Other common moves are getRowCount() → rows.getCount(), getRowData(i) → rows.getData(i), and setCellValue(row, col, value) → cells.setValue(row, col, value). There are no root-level forwarding methods. See the complete namespace mapping.

Editing, writes, and refresh

  • Editor commits are coerced by cellDataType: a number-column draft "60000" stores 60000. An invalid draft writes nothing and reports type-mismatch through onWriteRejected.
  • onWriteCommitted reports one event per edit, paste, fill, or programmatic write, including skipped targets. It requires getRowId; history: { maxEntries } enables bounded undo and redo and also requires getRowId.
  • Columnar sources are read-only. Group and total rows cannot be edited; writes report not-a-record. Row dragging is disabled while a hierarchy is bound.
  • core.rows.getData(i) returns a resident source record only. Use getViewRow(i) and narrow on kind before reading a hierarchical record; columnar rows have no materialized record.
  • Mutable source subscriptions are handled by the wrapper. Update-only transactions redraw changed rows without a query, preserving row position even if a sorted or filtered field changes. Call core.refresh() to re-sort or re-filter immediately. Adds, removes, and clearing reload the view.

Labels, sizing, and server rendering

GridLabelOverrides remains partial. A full GridLabels object must add pinLeftColumn, pinRightColumn, unpinColumn, frozenRowsLimited, columnSchemaErrors, and rowGroups including loadFailed.

The header stays fixed. Cells fill their row height through the shipped stylesheet; remove custom inline cell heights that conflict with the row box. Rows resize only through application commands, gestures, or one-shot fit, rather than growing automatically with content.

Pass initialWidth and initialHeight for server rendering. Controlled columnState and columnLayout seed the initial layout. Header bands use configured heights until client measurements refine them.

ARIA row indices include header bands, and aria-rowcount includes the headers. Hierarchical views use role="treegrid", and core.rows.getCount() includes groups and totals. Sort, filter-popup, and pin header controls remain pointer-only.

Shared core changes

Review the core migration reference if you consume geometry, instructions, complete label objects, saved filters, or custom adapter types. It covers exclusive window ends, required slot heights and row regions, removed exports, schema command return values, and legacy filter normalization.

Source: upstream migration guide.

On this page