Export
Export the entire filtered result — not just the current page — streamed to the client in bounded key-range windows. Memory stays flat regardless of size. Measured through the HTTP endpoint: 1.67M rows (6 columns) in ~52 s at constant memory.
Server
GridDefinition::export() returns a StreamedResponse:
use Elyra\DataGrid\Protocol\GridRequest;
Route::post('/api/sales/export', fn (Request $r) => salesGrid()->export(
GridRequest::fromArray(json_decode($r->input('request'), true) ?: []),
'csv', // 'csv' (default) | 'xlsx'
'sales', // filename (without extension)
));
The export honors the request's columns, filter and search, ignores paging (it streams everything that matches), and orders by the key column for a stable, single-pass scan.
Formats
| Format | Notes |
|---|---|
csv (default) |
UTF-8 with BOM + ; delimiter (opens cleanly in Excel). No dependencies. |
xlsx |
Rich styling (bold header band, right-aligned numeric columns with a #,##0.00 number format, sensible column widths). Requires openspout/openspout; falls back to CSV if not installed. |
How it streams (ElyraSQL)
ElyraSQL constrains how a large result can be read: unbuffered cursors corrupt
the socket under non-CLI SAPIs, one huge buffered transfer fails, and open-ended
key > ? seeks are full scans. What is fast and reliable is a double-bounded
key window (key >= a AND key < b). So for a numeric key the exporter walks
the result in fixed key-range windows — each a small, bounded, index-friendly
read — streaming rows out as it goes. This keeps memory flat and works across
SAPIs (built-in server, fpm, CLI). The streamed response sets set_time_limit(0).
Grids without a numeric key fall back to a single buffered read (bounded by the
result size). Add a compound (key)/(filterColumn, key) index for the fastest
windows on very large tables.
composer require openspout/openspout # optional, for real .xlsx
Livewire
Enable the toolbar button; it calls export() directly:
class SalesGrid extends DataGrid
{
public bool $exportable = true;
public string $exportFormat = 'csv'; // or 'xlsx'
}
Vue / Svelte
Set exportUrl; the toolbar button submits the current request to it (a form
POST that triggers a browser download):
const options = { /* ... */ exportUrl: '/api/sales/export' };
grid.exportData(); // programmatic
The client posts a request field (JSON of the current GridRequest) plus the
CSRF token. Make sure the endpoint is reachable — for a plain POST route, add it
to the CSRF exceptions (see Inertia integration).
Why this beats client-side export
Client-only grids can only export the rows they have loaded. Because Elyra DataGrid streams from the database, you can export the full result set — millions of rows — with constant client and server memory.