Lattice Grid Buy a licence

demo D161

Grid state in a URL in Angular

Sort, filter and reorder, then share the whole arrangement as a short link

serialiseState() · restoreState()

This grid encodes its whole arrangement, the sort, filters and column order, into a short link that restores the same view when opened. It lets a person share the exact view they built by sending a URL, with no saved-view storage required.

Building…
Loading a live grid…

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, ViewChild } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { createGrid, serialiseState, restoreState } from '@toclocoinc/lattice-grid';
import '@toclocoinc/lattice-grid/css';
import { LatticeGridComponent, provideLattice } from '@toclocoinc/lattice-grid/angular';

const columns = [
  { field: 'ref', title: 'Invoice', layout: { pin: 'start', width: 140 } },
  { field: 'supplier', title: 'Supplier', layout: { flex: 1, min: 180 }, filter: { type: 'set' } },
  { field: 'region', title: 'Region', filter: { type: 'set' } },
  { field: 'quantity', title: 'Qty', type: 'number', layout: { width: 90 } },
  { field: 'amount', title: 'Amount', type: 'number', total: 'sum', layout: { width: 150 } },
];

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [LatticeGridComponent],
  template:
    '<lattice-grid [config]="grid" (state-changed)="show()" (grid-ready)="onGridReady()" style="display:block;height:480px"></lattice-grid>' +
    '<p>Shareable link: <code>{{ link }}</code></p>',
})
export class AppComponent {
  @ViewChild(LatticeGridComponent) gridRef!: LatticeGridComponent;
  link = '';

  grid = {
    rowKey: 'id',
    selection: 'multiple',
    columns,
    rows: [/* your data */],
  };

  // The link carries the whole view. The encoding is a diff against the grid's
  // defaults, so an untouched grid is a few characters and only what changed is
  // carried.
  show() {
    const grid = this.gridRef && this.gridRef.grid;
    if (grid) this.link = location.pathname + '?view=' + serialiseState(grid);
  }

  // A shared link rebuilds the view: if the page was opened with a ?view=, apply
  // it, then keep the link in step as the visitor sorts or filters. The grid is
  // created once the view has rendered, so the live instance arrives on
  // grid-ready rather than in ngAfterViewInit.
  onGridReady() {
    const grid = this.gridRef.grid;
    const view = new URLSearchParams(location.search).get('view');
    if (view) restoreState(grid, view);
    this.show();
  }
}

bootstrapApplication(AppComponent, {
  providers: [provideLattice({ createGrid })],
});

A grid a person has sorted, filtered and reordered is a view they built, and the usual way to let them keep it is a saved view stored somewhere. serialiseState takes the other route: it encodes that whole arrangement, the sort, the filters, the column order and widths, the grouping and the selection, into a compact, URL-safe string. It is diffed against the grid’s own defaults first, so an untouched grid encodes to a few characters and only what the visitor actually changed is carried. restoreState reads the string back and rebuilds the view.

The grid above keeps that string live in the bar over it as you drive the grid, and the whole point is what it lets you do next: paste it into a URL. A colleague who opens that link sees exactly the grid you were looking at, because the page reads the ?view= on load and restores it, and none of it touched a server. The state is small enough to sit in a query string, honest enough to diff against the defaults rather than dump everything, and it is the same primitive the htmx module leans on to survive a swap.

How do you save and share a grid’s sort and filters in a URL?

Call serialiseState(grid) to get a short, URL-safe string of everything grid.state covers, and put it in the query string, for example ?view= followed by that value. On the next visit, read the parameter and pass it to restoreState(grid, value) to rebuild the sort, filters, column order and the rest. Because the encoding is a diff against the grid’s defaults, an unchanged grid is a handful of characters and the link only grows with what the user changed.