we-grid, screen by screen

Every image below is a real screen from one of the three sample applications in this repository — no mockups, no marketing renders. Each one is captioned with the sample app it came from, so you can run it yourself and land on the same screen.

$ npm install we-grid-angular @angular/cdk

Looking for the code rather than the pictures? How to use we-grid walks through installation, the column definition and types, filtering the whole table on the server, export/import and inline row editing.

Sample apps
3
Unit tests
282 passing
CSS framework deps
0
Icon font deps
0 — inline SVG
Angular
18 – 22
License
MIT
[serverSide]="true"

500 orders, one page at a time

The grid never pages by itself. It renders the rows you hand it and reports what the user asked for — page, sort, filter — as events. Here the mock backend answers each one, and the KPI cards above the grid are computed over the whole filtered set, not the 25 visible rows.

Order operations dashboard: five KPI cards above a grid of orders with status badges and a pinned order number column.
ecommerce-dashboard — npm run start:ecommerce orders.xml, parsed with DOMParser
contextmenu on <th>

Everything the end user is allowed to change

Right-click a header — or use the gear button on it — and the whole column vocabulary is there: hide, rename, pin, sort, fit width to content, pick a subtotal function, switch density, group by this field, reset. No host-app wiring; the grid owns this menu.

Header context menu listing hide column, columns, show all columns, group by this field, rename, wrap text, fit width to content, pin, sort, summary, density and reset layout.
retail-market — npm run start:retail menu on the Category column
(filterChange)

Filter row, chips, and totals that follow

Free-text, date and amount columns get an operator and a value; closed-set columns like City get a checklist button. Active filters collapse into removable chips above the header. Ticking Fallowick in City takes 500 orders down to 26 — every page of them, because the filter runs on the backend — and the revenue and cancellation figures move with it. The pill on the right flips once a layout has been saved for this user.

The same dashboard with a City filter applied: a City Fallowick chip, 26 matching orders, and recomputed KPI values.
ecommerce-dashboard contains · startsWith · equals · between · tri-state boolean · checklist
headerFilterMode: 'checklist'

Tick the values, not the operator

Every filterable column's funnel opens this by default: the distinct values — here of every order, through checklistValuesProvider, not just the loaded page — searchable, with a select-all box and an entry for blanks — and the selection leaves as a single 'in' filter carrying the raw codes, which the backend turns into one IN (…) over every order. The labels come from the column's displayValue, so the user ticks "Shipped" while the query gets 40.

The Status column's funnel icon opened into a checklist of the six order statuses, with Preparing and Shipped ticked and a search box above them.
ecommerce-dashboard multi (checkbox) or single (radio) · search · select all · (Empty)
[grouping]="true"

Grouped, subtotalled, and selected

Grouping by a column turns the body into collapsible sections, each header carrying its own subtotals — here a sale-price average and a stock sum per category. Selection is the host app's business: the grid reports it, the sample turns it into a bulk action bar with the retail value of what is ticked. The note above the grid is the other half of this sample: filters and checklists cover all 400 products on the server, not the 50 on screen.

Products grouped by category with per-group subtotals, three rows selected, and a bulk action bar showing the selected retail value.
retail-market rowClass highlighting on critical stock · density switch
*weGridRowDetail

A row that opens into its own breakdown

Master-detail is an Angular template you project into the grid, so the detail area is ordinary markup in your component with your own styles applied. The account number column stays pinned to the left while the rest of the table scrolls sideways under it.

Bank account transactions with the first row expanded into a fee breakdown table showing principal, transaction fee and fee tax lines.
banking — npm run start:banking per-row currencies · pinned column · date-range filter
data-theme="dark"

Dark mode is one attribute

Every colour in the grid is a --we-grid-* custom property. Setting data-theme="dark" on any ancestor switches the whole set; leaving it off follows the operating system instead. There is no theme input, no second stylesheet, and nothing to rebuild — override the properties and the grid is in your brand.

The order dashboard in dark theme, with the status badges and KPI cards adapted to the dark palette.
ecommerce-dashboard the Dark theme button sets one attribute on <html>
WeGridLayout

The layout belongs to the user, not the code

Which columns are visible, how wide they are, what they are called, where they are pinned and in what order — all of it is saved under the grid's gridKey and restored on the next visit. localStorage is the default; implement one interface and it goes to your backend per user instead.

The columns submenu open, listing each column with a checkbox controlling its visibility.
ecommerce-dashboard custom WeGridLayoutStore — see user-layout-store.ts

Run these screens yourself

Clone the repository, build the library once, then serve any of the three sample apps. The datasets are generated from a seeded PRNG and entirely fictional, so your screens will match the ones above row for row.

git clone https://github.com/emrecirik/we-grid.git
cd we-grid
npm install
npm run build:lib          # required before any app builds
npm run start:ecommerce    # or start:banking / start:retail