demo D227
Cross-filtering, the path back up
Two summary panels over one book; click a row in either and it filters the book, so the other narrows
crossFilter: true · crossFilter.toggle
Loading a live grid…
The configuration
import * as ng from '@angular/core';
import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { bootstrapApplication } from '@angular/platform-browser';
import { createGrid } from '@toclocoinc/lattice-grid';
import '@toclocoinc/lattice-grid/css';
import createLatticeGrid from '@toclocoinc/lattice-grid/modules/angular';
const { LatticeGridComponent } = createLatticeGrid({ ng, createGrid });
const USD = { style: 'currency', currency: 'USD', maximumFractionDigits: 0 };
const bookColumns = [
{ field: 'rep', title: 'Rep' },
{ field: 'region', title: 'Region' },
{ field: 'amount', title: 'Deal', type: 'number', format: USD, total: 'sum' },
];
const regionColumns = [
{ field: 'region', title: 'Region' },
{ field: 'revenue', title: 'Revenue', type: 'number', format: USD },
];
const repColumns = [
{ field: 'rep', title: 'Rep' },
{ field: 'revenue', title: 'Revenue', type: 'number', format: USD },
];
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule, LatticeGridComponent],
template:
'<lattice-grid #book [config]="bookGrid" style="display:block;height:300px"></lattice-grid>' +
'<div style="display:flex;gap:16px;margin-top:16px">' +
' <lattice-grid #regionGrid *ngIf="byRegion" [config]="byRegion" (ready)="wire(regionGrid)" style="flex:1"></lattice-grid>' +
' <lattice-grid #repGrid *ngIf="byRep" [config]="byRep" (ready)="wire(repGrid)" style="flex:1"></lattice-grid>' +
'</div>',
})
export class AppComponent implements AfterViewInit {
@ViewChild('book') bookRef!: LatticeGridComponent;
byRegion: any = null;
byRep: any = null;
bookGrid = { rowKey: 'id', toolPanel: { side: 'left', panels: ['filters', 'columns'] }, columns: bookColumns, rows: [/* e.g. { id: 'S0', rep: 'Ana', region: 'EMEA', amount: 1830 } */] };
// Each summary panel derives from the live book and follows its filter.
// crossFilter: true lets a panel push the clicked group onto the book as an
// ordinary filter, so the other panel re-derives and both narrow each other
// while staying whole.
ngAfterViewInit() {
const book = this.bookRef.grid;
const panel = (col: string) => ({ autoHeight: true, columns: col === 'region' ? regionColumns : repColumns, source: { mode: 'derived', from: book, follow: 'filtered', refresh: 'live', groupBy: col, crossFilter: true,
select: { revenue: { of: 'amount', fn: 'sum' }, deals: { fn: 'count' } }, sort: [{ col: 'revenue', dir: 'desc' }] } });
this.byRegion = panel('region');
this.byRep = panel('rep');
}
// A click on a panel row toggles that group as the book's filter.
wire(cmp: LatticeGridComponent) {
const g = cmp && cmp.grid;
if (g) g.on('row:click', (e: any) => g.crossFilter.toggle(e.key));
}
}
bootstrapApplication(AppComponent);