DataGrid · · 5 min read

We built the data grid we always wished existed

Meet Elyra DataGrid — one grid, three clients, ten million rows, and a first paint that doesn't flinch.

We built the data grid we always wished existed

Meet Elyra DataGrid — one grid, three clients, ten million rows, and a first paint that doesn't flinch.

There's a moment every Laravel developer knows well. The feature request lands: "Can we just show all the orders in a table? With sorting, filtering, maybe grouping. Oh, and it should be fast."

You reach for a grid. And then the compromises begin.

The pretty client-side grid chokes the moment the table crosses a few thousand rows — because it wants everything in the browser. The powerful one is married to a single frontend, so it's useless the day you add a second app. The "headless" one hands you primitives and a weekend of homework. Somewhere around midnight you're hand-rolling pagination SQL again, and wondering why, in 2026, this is still hard.

Elyra DataGrid is our answer to that midnight. It's a professional data grid for the Laravel ecosystem, built around a simple idea: the database should do the heavy lifting, the browser should stay light, and you shouldn't have to pick a frontend to get either.

Why: the database already knows how to do this

Sorting, filtering, grouping, aggregating, paging — your database has been ruthlessly good at these for decades. So Elyra DataGrid doesn't fight it. Every operation is a query, pushed down to the database. The client only ever renders the slice you can actually see.

That one decision changes everything. The grid behaves the same over 100 rows and 10,000,000 rows, because the work is O(viewport), not O(data). We didn't tune our way there — it's structural.

It's also native to ElyraSQL, which turns database superpowers straight into grid features:

  • Faceted "filter by checkbox, with counts" in a single pass (FACET)

  • Group subtotals and percentile/median columns

  • Hybrid semantic + full-text search

  • Streamed exports of the entire filtered result — millions of rows, flat memory

(Prefer plain MySQL? It works there too, with a graceful fallback.)

How: define once on the server, render anywhere

You describe the grid on the server — which is also your security boundary. Only declared columns ever touch SQL; every value is bound.

use Elyra\DataGrid\Server\Grid;

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,delivered,returned') ->column('qty', type: 'number', editable: true, rules: 'required|integer|min:0') ->column('revenue', type: 'number') ->searchable(['sku', 'category']); }

That's the whole contract. Now pick a client.

Livewire + Flux UI — server-driven, the least JavaScript, and it inlines its own theme:

class SalesGrid extends \Elyra\DataGrid\Livewire\DataGrid
{
public bool $searchable = true;
public bool $groupable  = true;
public bool $editable   = true;
public string $editMode = 'incell';   // inline · modal · slideover · incell
public bool $batchEdit  = true;       // edit many cells, save once

protected function definition(): GridDefinition { return salesGrid(); }
protected function columns(): array { /* display config */ }

}

Vue 3 + Inertia — the same grid, now an SPA experience:

<script setup lang="ts">
import { DataGrid, laravelFetch } from '@elyra/datagrid-vue';

const options = { key: 'id', columns: [ { field: 'sku', header: 'SKU', frozen: 'left' }, { field: 'revenue', header: 'Revenue', type: 'number', cell: { type: 'currency', symbol: 'kr ', decimals: 2 } }, { field: 'margin', header: 'Margin', frozen: 'right', cell: { type: 'bar', max: 1200 } }, ], fetch: laravelFetch('/api/sales/grid'), initialData: props.initial, // server-seeded → instant first paint filtering: { builder: true }, // advanced AND/OR filter builder grouping: { detailRows: true }, // drill into a group's rows }; </script>

<template><DataGrid :options="options" heading="Sales" /></template>

Svelte 5 + Inertia — identical options, runes under the hood. Same protocol, same theme, same features. You learn it once.

And because it's one shared protocol generating both TypeScript types and PHP DTOs, the three clients are genuinely interchangeable. Build in Livewire today, add a Vue app next quarter, reuse everything.

The bits that feel good

  • First paint that's instant. Server-seed the first page as an Inertia prop and the grid is populated before the first client round-trip.

  • Editing, your way. Inline, modal, slide-over, or spreadsheet-style in-cell — with optional batch mode: edit a stack of cells, review the highlighted changes, save once.

  • A filter row that's discreet, plus an AND/OR builder for the power users.

  • Grouping with real subtotals — and correct averages, medians, and percentiles at every level, because each level is computed properly, not faked.

  • Frozen columns (left and right), auto-fit, column reorder/resize, multi-column headers, virtual rows and virtual columns.

  • A full keyboard story — arrows, Home/End, Page keys, range select, copy/paste TSV, edit with Enter/F2.

  • A theme that follows your app. It reads your Tailwind v4 palette and Flux accent, does dark mode by the .dark class, and can be reskinned with a single token. It looks like it belongs on day one.

Why it's better

Not louder — better, in the way that matters six months in:

  1. It stays fast because of its shape, not your luck. On a 10M-row table, paging and index-backed sorting land around ~30 ms. The expensive things (row counts, aggregates, facets) are opt-in and cached per filter — you pay for them once, then paging and sorting reuse them. An export of 1.67 million rows streams in seconds at flat memory.

  2. One contract, not one frontend. Most grids make you marry a stack. This one hands the same grid to Livewire, Vue, and Svelte from a single server definition. No lock-in, no rewrite when your architecture grows.

  3. It's honest about the trade. It expects a Laravel backend and shines with ElyraSQL — and in return you get scale that client-only grids simply can't reach. Export everything. Facet everything. Search by meaning. On real volume.

  4. It's finished. Server-validated editing, streamed rich XLSX, i18n, state persistence, SSR-friendly first paint, an app-following theme, and a genuinely complete keyboard spec. The things you'd otherwise bolt on for weeks are already here.

Simple by default, configurable to advanced

A working grid is four lines. Every feature is false | true | { …options } — omit it, accept sensible defaults, or take full control. Cost is opt-in. Security is by allow-list. The grid follows your app.

That's the whole philosophy, and it's why Elyra DataGrid is the grid we reach for now — the one we wish we'd had all those midnights ago.

Elyra DataGrid — enterprise-grade, delightfully calm.elyracode.com