Chapter 10 of 34
One model, every framework
Svelte 4/5, Solid and Preact – the model stays the same, only the event syntax changes.
After this chapter you can
- compare the event syntax of all wrappers
- use Svelte 5 callback props
- avoid two Solid runtimes
The same model everywhere
All framework demos import one function – createOrderTableModel() from
chapter 6. The
TableModelIf knows nothing about frameworks; only the event syntax differs.
| Framework | Package | Events |
|---|---|---|
| Plain TS | @guiexpert/table | EventAdapter / own EventListenerIf |
| Web Component | @guiexpert/webcomponent-table | addEventListener("tableReady", e => e.detail) |
| React / Preact / Solid | @guiexpert/react-table / preact-table / solid-table | props tableReady={api => …} |
| Vue 3 | @guiexpert/vue3-table | @tableReady="onReady" |
| Svelte 4 / 5 | @guiexpert/svelte-table | on:tableReady resp. Svelte 5: onTableReady={api => …} |
| Angular 14–22 | @guiexpert/angular-table@NN | (tableReady)="onReady($event)" |
Svelte 5 (runes)
npm i @guiexpert/table @guiexpert/svelte-table<!-- Episode 010 – Svelte 5 (runes): callback props instead of on:… events. --><script lang="ts"> import { GuiexpertTable } from "@guiexpert/svelte-table"; import { type GeMouseEvent, type TableApi, TableOptions } from "@guiexpert/table"; import { createOrderTableModel } from "./model/order-table";
const tableModel = createOrderTableModel(100_000); const tableOptions = { ...new TableOptions() }; let info = $state("");</script>
<header class="app-header"><b>Svelte 5</b> <span id="info">{info}</span></header><div class="table-div"> <GuiexpertTable {tableModel} {tableOptions} onTableReady={(api: TableApi) => (info = `${api.getBodyModel().getRowCount()} orders`)} onMouseClicked={(evt: GeMouseEvent) => (info = `row ${evt.rowIndex}, column ${evt.columnIndex}`)} /></div>
The package ships Svelte source, compiled by your Svelte – so it runs under Svelte 4 and 5. In Svelte 5
use the callback props (onTableReady, onMouseClicked …); in Svelte 4 the
on:tableReady events with e.detail.
Solid
// Episode 010 – Solid: callback props like React.import { GuiexpertTable } from "@guiexpert/solid-table";import { GeMouseEvent, TableApi, TableOptions } from "@guiexpert/table";import { createSignal } from "solid-js";import { createOrderTableModel } from "./model/order-table";
export function App() { const [info, setInfo] = createSignal(""); const tableModel = createOrderTableModel(100_000); const tableOptions = { ...new TableOptions() }; return ( <> <header class="app-header"><b>Solid</b> <span id="info">{info()}</span></header> <div class="table-div"> <GuiexpertTable tableModel={tableModel} tableOptions={tableOptions} tableReady={(api: TableApi) => setInfo(`${api.getBodyModel().getRowCount()} orders`)} mouseClicked={(evt: GeMouseEvent) => setInfo(`row ${evt.rowIndex}, column ${evt.columnIndex}`)} /> </div> </> );}import { defineConfig } from "vite";import solid from "vite-plugin-solid";
export default defineConfig({ plugins: [solid()], resolve: { dedupe: ["solid-js"] }, // exactly one Solid runtime for app and @guiexpert/solid-table server: { fs: { allow: ["../.."] } }});Preact
// Episode 010 – Preact: same callback props as React.import { GuiexpertTable } from "@guiexpert/preact-table";import { GeMouseEvent, TableApi, TableOptions } from "@guiexpert/table";import { useMemo, useState } from "preact/hooks";import { createOrderTableModel } from "./model/order-table";
export function App() { const [info, setInfo] = useState(""); const tableModel = useMemo(() => createOrderTableModel(100_000), []); const tableOptions = useMemo(() => ({ ...new TableOptions() }), []); return ( <> <header class="app-header"><b>Preact</b> <span id="info">{info}</span></header> <div class="table-div"> <GuiexpertTable tableModel={tableModel} tableOptions={tableOptions} tableReady={(api: TableApi) => setInfo(`${api.getBodyModel().getRowCount()} orders`)} mouseClicked={(evt: GeMouseEvent) => setInfo(`row ${evt.rowIndex}, column ${evt.columnIndex}`)} /> </div> </> );}Takeaway
Write your table model and options once, in plain TypeScript, and test them without a framework. Switching from React to Vue – or using the same table in an Angular admin app and a Svelte dashboard – only changes a dozen lines of glue code. Part 4 is all about that model: chapter 11 (TableModel & areas).