Data Sources
Connect the Vue 3 grid to client-side arrays or server-side endpoints, and plug streaming, paginated, or fully remote data flows into gp-grid with ease.
gp-grid provides data source abstractions shared with the React package.
Basic Usage
<script setup>
const data = ref([
{ id: 1, name: "Giovanni" },
{ id: 2, name: "Luca" },
]);
</script>
<template>
<Grid :row-data="data" ... />
</template>Client Data Source
<script setup>
import { createClientDataSource } from "@gp-grid/vue";
const dataSource = createClientDataSource(largeDataset, {
useWorker: true, // Web Worker for sorting
});
</script>
<template>
<Grid :data-source="dataSource" ... />
</template>Mutable Data Source
For CRUD operations, use the useGridData composable inside <script setup>. It wraps createMutableClientDataSource with a stable reference and exposes addRows / removeRows helpers bound to the current data source.
<script setup>
import { useGridData } from "@gp-grid/vue";
const { dataSource, addRows, removeRows } = useGridData(data, {
getRowId: (row) => row.id,
});
function addRow() {
addRows([{ id: Date.now(), name: "New" }]);
}
function updateRow(id: number, name: string) {
dataSource.updateCell(id, "name", name);
}
function deleteRow(id: number) {
removeRows([id]);
}
</script>Reach for the raw createMutableClientDataSource factory only outside components — module-level singletons, composables that need their own lifecycle, or shared utilities. Inside a component, prefer useGridData: it handles subscription cleanup on unmount and keeps the dataSource reference stable across re-renders.
// Outside a component (e.g. a shared module)
import { createMutableClientDataSource } from "@gp-grid/vue";
export const sharedDataSource = createMutableClientDataSource(seed, {
getRowId: (row) => row.id,
});useGridData Options
interface UseGridDataOptions<TData> {
getRowId: (row: TData) => RowId; // Required: unique ID accessor
debounceMs?: number; // Batch window (default: 50)
useWorker?: boolean; // Use Web Worker for sorting (default: true)
parallelSort?: ParallelSortOptions | false;
}MutableDataSource Methods
interface MutableDataSource<TData> extends DataSource<TData> {
addRows(rows: TData[]): void;
removeRows(ids: RowId[]): void;
updateCell(id: RowId, field: string, value: CellValue): void;
updateRow(id: RowId, data: Partial<TData>): void;
flushTransactions(): Promise<void>;
hasPendingTransactions(): boolean;
getDistinctValues(field: string): CellValue[];
getRowById(id: RowId): TData | undefined;
getTotalRowCount(): number;
subscribe(listener: DataChangeListener): () => void;
clear(): void;
moveRow(fromIndex: number, toIndex: number): void;
}DataSource Interface
All data sources implement the DataSource<TData> interface. Both createClientDataSource and createServerDataSource return objects that conform to it; MutableDataSource<TData> extends it with mutation methods.
interface DataSource<TData> {
readonly loadMode?: "all" | "paginated";
query(request: DataSourceRequest): Promise<DataSourceResponse<TData>>;
destroy?(): void;
moveRow?(fromIndex: number, toIndex: number): void;
}| Member | Required | Description |
|---|---|---|
loadMode | No | "all" (default for client data sources) or "paginated" (default for server). Controls whether the grid requests every row at once or only the visible window via range.startRow / range.endRow. |
query | Yes | Async function returning { rows, totalRows } for the requested range, sort, and filter. Called by the grid whenever the visible window, sort, or filter changes. |
destroy | No | Cleanup hook for releasing workers, sockets, or other resources. Called when the data source is detached from the grid. |
moveRow | No | Called on row drag-end. Implement it to update the underlying data; the grid does not mutate data on its own. |
Server Data Source
<script setup>
import { createServerDataSource } from "@gp-grid/vue";
const dataSource = createServerDataSource(async (request) => {
const { range, sort, filter } = request;
const response = await fetch("/api/data", {
method: "POST",
body: JSON.stringify({
startRow: range.startRow,
endRow: range.endRow,
sortBy: sort,
filters: filter,
}),
});
return response.json();
});
</script>
<template>
<Grid :data-source="dataSource" ... />
</template>Pass { loadMode: "all" } as a second argument if the server returns the entire result set in one call. The default is "paginated" — the grid only requests the row window currently in view via range.startRow / range.endRow.
const dataSource = createServerDataSource(queryFn, { loadMode: "paginated" });Request / Response
interface DataSourceRequest {
range: {
startRow: number; // First row index to fetch (0-indexed, inclusive)
endRow: number; // First row index after the range (exclusive)
};
sort?: SortModel[];
filter?: FilterModel;
}
interface DataSourceResponse<TData> {
rows: TData[];
totalRows: number;
}With Nuxt useFetch
<script setup>
const dataSource = createServerDataSource(async (request) => {
return await $fetch("/api/grid-data", {
method: "POST",
body: request,
});
});
</script>Reactive Updates
Data sources work with Vue's reactivity:
<script setup>
const data = ref<User[]>([]);
// Fetch initial data
onMounted(async () => {
data.value = await fetchUsers();
});
// Grid automatically updates when data.value changes
</script>
<template>
<Grid :row-data="data" ... />
</template>