Inertia integration (Svelte / Vue)
The Svelte and Vue clients are client-driven: a headless engine calls a fetch
function that POSTs the protocol request to a Laravel endpoint. This guide covers
the endpoints, CSRF, and server-seeded first paint.
Endpoints
Define the grid once and reuse it across the page, grid, mutate and export routes:
use Elyra\DataGrid\Protocol\GridRequest;
use Elyra\DataGrid\Protocol\GridMutation;
use Elyra\DataGrid\Server\Grid;
use Illuminate\Http\Request;
function salesGrid()
{
return Grid::table('sales')->connection('elyrasql')->key('id')
->columns(['id', 'sku', 'region', 'category', 'status'])
->column('status', editable: true, editor: 'select', rules: 'required|in:pending,paid,shipped')
->column('qty', type: 'number', editable: true, rules: 'required|integer|min:0')
->column('revenue', type: 'number')
->searchable(['sku', 'category']);
}
Route::get('/sales', fn () => Inertia::render('Sales', [
'initial' => salesGrid()->respond(GridRequest::fromArray([
'columns' => ['id', 'sku', 'region', 'category', 'status', 'qty', 'revenue'],
'view' => ['skip' => 0, 'take' => 20],
'meta' => ['total'],
])),
]));
Route::post('/api/sales/grid', fn (Request $r) => salesGrid()->respond(GridRequest::fromArray($r->all())));
Route::post('/api/sales/mutate', fn (Request $r) => salesGrid()->mutate(GridMutation::fromArray($r->all())));
Route::post('/api/sales/export', fn (Request $r) => salesGrid()->export(
GridRequest::fromArray(json_decode($r->input('request'), true) ?: []), 'csv', 'sales'));
CSRF
The laravelFetch helper posts JSON. The simplest approach for API-style grid
endpoints is to exempt them from CSRF in bootstrap/app.php:
->withMiddleware(function (Middleware $middleware): void {
$middleware->validateCsrfTokens(except: ['api/*']);
})
Alternatively keep CSRF and add a <meta name="csrf-token"> tag —
laravelFetch sends it as X-CSRF-TOKEN.
Server-seeded first paint (initialData)
A client-fetched grid is empty on first paint until its XHR resolves. Pass the
first page as an Inertia prop and hand it to the grid as initialData — the grid
renders immediately and only fetches on interaction:
<script setup lang="ts">
import { DataGrid, laravelFetch } from '@elyra/datagrid-vue';
import type { GridResponse } from '@elyra/datagrid-vue';
const props = defineProps<{ initial?: GridResponse }>();
const options = {
key: 'id',
columns: [ /* ... */ ],
fetch: laravelFetch('/api/sales/grid'),
initialData: props.initial, // ← instant first paint
};
</script>
This also improves perceived performance and works well with Inertia SSR.
The laravelFetch helper
import { laravelFetch } from '@elyra/datagrid-vue'; // or -svelte
const fetch = laravelFetch('/api/sales/grid');
It POSTs the GridRequest as JSON with Accept: application/json, X-CSRF-TOKEN
(from the meta tag, if present) and X-Requested-With. You can provide any
(request) => Promise<GridResponse> if you need custom behavior.
Custom mutate
editing.mutate is any (GridMutation) => Promise<GridMutationResult>:
editing: {
mode: 'slideover',
mutate: async (m) => (await fetch('/api/sales/mutate', {
method: 'POST',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
body: JSON.stringify(m),
})).json(),
},