demo D284
A feed enriched from a lookup in ESM
One order feed joined to a customer lookup, held until known and released enriched
addSource(join: { from, localKey, fields, missing: 'hold' })
This joins a live order feed to a customer lookup as the rows arrive, holding each order until its customer is known and then releasing it enriched. It fills in the name and tier a reader actually wants, so incomplete live records arrive complete.
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: 360px"></div>
<div id="customers" style="height: 360px"></div>
<script type="module">
import { createDataRouter } from '@toclocoinc/lattice-grid/modules/data-router';
const money = { style: 'currency', currency: 'USD', decimals: 0 };
const tierPill = { decoration: 'pill', variant: { map: { Gold: 'warning', Silver: 'neutral', Bronze: 'info' } } };
const ordersGrid = createGrid(document.getElementById('orders'), {
rowKey: 'id',
columns: [
{ field: 'id', title: 'Order', layout: { width: 110, pin: 'start' } },
{ field: 'customerId', title: 'Cust. id', layout: { width: 100 } },
{ field: 'name', title: 'Customer' }, // brought across by the join
{ field: 'tier', title: 'Tier', cell: tierPill, layout: { width: 110 } }, // brought across too
{ field: 'amount', title: 'Amount', type: 'number', format: money, total: 'sum' },
],
});
const custGrid = createGrid(document.getElementById('customers'), {
rowKey: 'id', edit: true,
columns: [
{ field: 'id', title: 'Id', layout: { width: 90, pin: 'start' } },
{ field: 'name', title: 'Customer' },
{ field: 'tier', title: 'Tier', edit: true, cell: tierPill, layout: { width: 120 } },
],
});
const router = createDataRouter({ key: 'kind', rowKey: 'id' });
router.attach(ordersGrid, 'order');
router.attach(custGrid, 'customer');
// Two feeds fanned in. The order feed names the customer feed as its lookup,
// brings name and tier across on the way in, and holds an order until its
// customer is known (missing: 'hold') rather than showing it half-filled.
const ordersSrc = router.addSource('orders', {
join: { from: 'customers', localKey: 'customerId', foreignKey: 'id', fields: ['name', 'tier'], missing: 'hold' },
});
const customersSrc = router.addSource('customers');
customersSrc.load(knownCustomers); // { id, kind: 'customer', name, tier }
ordersSrc.load(orders); // { id, kind: 'order', customerId, amount }
// Load the rest of the customers later and the held orders release already
// enriched; correcting a tier in the customer grid re-enriches the orders.
// customersSrc.load(allCustomers);
</script>
One feed, enriched from a lookup as it arrives
Live records rarely arrive complete. An order comes in carrying a customer id and an amount, and the name and tier a reader actually wants live in a separate customer list. The data router joins the two as the feed arrives: an order source names the customer source as its lookup, brings the chosen fields across, and hands the grid a row that already carries the name and tier. You configure the join once, addSource('orders', { join: { from: 'customers', localKey: 'customerId', fields: ['name', 'tier'] } }), and every order from then on is enriched on the way in.
The interesting case is the order that arrives before its customer is known. Setting missing: 'hold' withholds that order rather than showing it half-filled with blank columns; when the customer feed loads, the held orders release and arrive already enriched. Both sides stay live, so a corrected tier in the customer list re-enriches the orders that point at it, and the grid reading the orders never has to know the join is happening.
How do I enrich a live feed with data from another source?
Add the lookup as a second source and give the main source a join: name the lookup in from, the field on your rows that matches it in localKey, and the fields to bring across in fields. Rows are enriched as they arrive. Set missing: 'hold' to withhold a row whose lookup is not known yet and release it once the lookup loads, so a reader never sees a half-filled record. Both sources stay live, so editing the lookup re-enriches the rows that depend on it.