demo D247
One feed, many views in ESM
Split a single live feed across two grids and a chart, with a pick in one narrowing another
createDataRouter
This splits a single live feed across two grids and a chart at once, and a pick in one narrows another. It gives a dashboard one source of truth shown in several places that all move together, without fanning the feed out to each view by hand.
This is the ES module version. The grid is imported straight from a CDN as a module, the same configuration as the vanilla tab without a global script tag, so it drops into any bundler or a bare module script.
The configuration
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.71.0/lattice-grid.min.css">
<div id="orders" style="height: 300px"></div>
<div id="returns" style="height: 300px"></div>
<div id="chart" style="height: 200px"></div>
<script type="module">
import { createDataRouter } from '@toclocoinc/lattice-grid/modules/data-router';
import { createChart } from '@toclocoinc/lattice-grid/modules/charts';
const money = { style: 'currency', currency: 'USD', decimals: 0 };
const orderCols = [
{ field: 'id', title: 'Ref', layout: { width: 110, pin: 'start' } },
{ field: 'region', title: 'Region', filter: { type: 'set' } },
{ field: 'service', title: 'Service', filter: { type: 'set' } },
{ field: 'value', title: 'Value', type: 'number', format: money, total: 'sum' },
];
// Three views of one feed. The two grids are painted; the metrics grid is
// headless and only feeds the chart.
const orders = createGrid(document.getElementById('orders'), {
rowKey: 'id', selection: 'multiple', highlightOnChange: { duration: 500 }, columns: orderCols,
});
const returns = createGrid(document.getElementById('returns'), {
rowKey: 'id', highlightOnChange: { duration: 500 }, columns: orderCols,
});
const metrics = createHeadlessGrid({
rowKey: 'ts',
columns: [{ field: 'ts', title: 'Tick', type: 'number' }, { field: 'value', title: 'Throughput', type: 'number' }],
});
// One partition key, three routes: a record's type decides which grid it
// reaches. link makes a selection in Orders narrow Returns to the same regions,
// re-pushed through the same keyed-diff path, so Returns stays a plain grid.
const router = createDataRouter({ key: 'type', rowKey: 'id' });
router.attach(orders, 'order');
router.attach(returns, 'return');
router.attach(metrics, 'metric', { rowKey: 'ts' });
router.link(orders, returns, { from: 'region', to: 'region' });
// The opening snapshot: one mixed list, partitioned in one call.
router.load(seed); // rows tagged type: 'order' | 'return' | 'metric'
createChart({ grid: metrics, container: document.getElementById('chart'),
type: 'line', x: 'ts', y: 'value', title: 'Throughput per tick' });
// A live delta each tick: { op: 'upsert' | 'delete', row }, applied in place by rowKey.
setInterval(() => router.apply(nextBatch()), 1400); // nextBatch(): an array of upserts
</script>
Splitting one live feed across several grids and a chart at once
Most dashboards carry a single source of truth that has to appear in several places at once: orders in one table, returns in another, throughput on a chart, all of it moving as the same events arrive. Lattice Grid does this without you fanning the feed out by hand. You hand createDataRouter one key to partition on, attach each grid or chart to the value it cares about, and from then on every event that arrives is delivered only to the views it belongs in, each through that view’s own incremental update path. One order lands in the orders table, one return in the returns table, one reading on the chart, and none of the three knows the others exist. Load an opening snapshot in a single call and it is split across every attached view for you; push a mixed batch of changes and each view takes only its share.
The views stay decoupled but need not stay unaware of one another. Cross-grid selection ties two grids together on a shared field: link the orders grid to the returns grid on region, pick an order, and the returns grid narrows to the same region on its own. A reader drills from one view into a related one with a single click, and the feed keeps arriving underneath the whole time. This is the shape behind an operations wall, a trading book split by desk, or any screen where one stream has to drive many honest, live views side by side.
How do I feed one data stream into multiple grids and a chart?
Create a router with createDataRouter({ key, rowKey }), then call router.attach(grid, value) for each grid or headless-grid-backed chart, naming the partition value it should receive. Load an initial snapshot with router.load(rows) and stream changes with router.apply([{ op: 'upsert', row }]); the router routes each record to the matching views only. Add router.link(source, target, { from, to }) to make a selection in one grid narrow another on a shared field.