demo D226
Joining a second grid in htmx
Orders carry a customer id but no tier; a join brings it across from a customers grid, then groups revenue by tier
join: { with, on, select }
Here orders carry a customer id but no tier, and a join brings the tier across from a separate customers grid, then groups revenue by it. It lets you enrich one dataset from another and report on the combined result, without flattening the two together beforehand.
This is the htmx version. A server-rendered table is upgraded in place, so the page is readable before any script runs and gains the full grid when the module loads, which suits a progressively enhanced app.
The configuration
<link rel="stylesheet" href="https://cdn.latticegrid.dev/lattice-grid@1.108.0/lattice-grid.min.css">
<div style="display: flex; gap: 16px">
<div id="orders" style="flex: 2; height: 300px"></div>
<div id="customers" style="flex: 1; height: 300px"></div>
</div>
<div id="byTier" style="margin-top: 16px"></div>
<script type="module">
import { createGrid } from 'https://cdn.latticegrid.dev/lattice-grid@1.108.0/modules/htmx.esm.min.js';
const USD = { style: 'currency', currency: 'USD', decimals: 0 };
// The two sides: orders carry a customerId, and the tier lives on the customer.
const customers = createGrid(document.getElementById('customers'), {
rowKey: 'id',
columns: [{ field: 'id', title: 'ID' }, { field: 'name', title: 'Customer' }, { field: 'tier', title: 'Tier' }],
rows: customerRows, // e.g. [{ id: 'C0', name: 'Acme', tier: 'Enterprise' }, …]
});
const orders = createGrid(document.getElementById('orders'), {
rowKey: 'id', toolPanel: { side: 'left', panels: ['filters', 'columns'] },
columns: [
{ field: 'customerId', title: 'Customer' },
{ field: 'region', title: 'Region', filter: { type: 'set' } },
{ field: 'amount', title: 'Value', type: 'number', format: USD, total: 'sum' },
],
rows: orderRows, // e.g. [{ id: 'O0', customerId: 'C0', region: 'EMEA', amount: 1240 }, …]
});
// The join brings tier across from the customers grid onto each order,
// matching customerId to id, then the group runs on that brought-across
// field. It runs before grouping, so a group can read a field the join made.
createGrid(document.getElementById('byTier'), {
autoHeight: true,
source: {
mode: 'derived', from: orders, follow: 'filtered', refresh: 'live',
join: { with: customers, on: { left: 'customerId', right: 'id' }, select: ['tier'] },
groupBy: 'tier',
select: { revenue: { of: 'amount', fn: 'sum' }, orders: { fn: 'count' } },
sort: [{ col: 'revenue', dir: 'desc' }],
},
columns: [
{ field: 'tier', title: 'Tier' },
{ field: 'revenue', title: 'Revenue', type: 'number', format: USD },
{ field: 'orders', title: 'Orders', type: 'number' },
],
});
</script>