demo D284
A feed enriched from a lookup in Angular
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 Angular version. A standalone component takes the whole configuration through one config input, surfaces grid events as outputs, and exposes the live grid on a getter for anything the inputs do not cover.
The configuration
import { Component, inject } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { createGrid } from '@toclocoinc/lattice-grid';
import '@toclocoinc/lattice-grid/css';
import { createDataRouter } from '@toclocoinc/lattice-grid/modules/data-router';
import { LatticeGridComponent, LatticeRouter, provideLattice, provideLatticeRouter } from '@toclocoinc/lattice-grid/angular';
const MONEY = { style: 'currency', currency: 'USD', decimals: 0 };
const TIER_PILL = { decoration: 'pill', variant: { map: { Gold: 'warning', Silver: 'neutral', Bronze: 'info' } } };
@Component({
selector: 'app-root',
standalone: true,
imports: [LatticeGridComponent],
providers: [provideLatticeRouter({ key: 'kind', rowKey: 'id' })],
template:
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:14px">' +
' <lattice-grid route="order" [config]="orderConfig" style="display:block;height:360px"></lattice-grid>' +
' <lattice-grid route="customer" [config]="customerConfig" style="display:block;height:360px"></lattice-grid>' +
'</div>',
})
export class AppComponent {
private routerService = inject(LatticeRouter);
orderConfig = {
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: TIER_PILL, layout: { width: 110 } }, // brought across too
{ field: 'amount', title: 'Amount', type: 'number', format: MONEY, total: 'sum' },
],
};
customerConfig = {
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: TIER_PILL, layout: { width: 120 } },
],
};
constructor() {
// 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 = this.routerService.router.addSource('orders', {
join: { from: 'customers', localKey: 'customerId', foreignKey: 'id', fields: ['name', 'tier'], missing: 'hold' },
});
const customersSrc = this.routerService.router.addSource('customers');
customersSrc.load([/* known customers: { id, kind: 'customer', name, tier } */]);
ordersSrc.load([/* orders: { id, kind: 'order', customerId, amount } */]);
}
}
bootstrapApplication(AppComponent, {
providers: [provideLattice({ createGrid, createDataRouter })],
});
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.