UI Grid

May 10, 2026 · View on GitHub

CI Coverage Status npm crates.io License: MIT

Discord Community

UI Grid — Remastered

The modern multi-platform data grid. Every feature free and open source. Built for Angular, Web-Components, React, native Rust/egui, and native C/LVGL.

A from-scratch rewrite of the original AngularJS ui-grid — by the original author. Same gridOptions / columnDefs / onRegisterApi api surface, modern Angular signals internals, and zero legacy baggage.

Just like the original grid, it will NEVER be monetized. This is purely my contribution to the greater community.

It proves that the datagrid cabal wants you to think it's hard to write a data grid. Well, it's not, and nobody should be paying to group data.

Live Demo & Docs | npm | crates.io | Used by NornicDB


Why Remastered?

  • Original authorship — built by the same engineer who created AngularJS ui-grid, with a decade of hindsight on what worked and what didn't
  • Familiar API — if you used the original ui-grid, you already know this one: gridOptions, columnDefs, onRegisterApi, gridApi.core.*
  • Modern internals — shared vanilla web component core with Shadow DOM encapsulation; Angular and React wrappers are thin bridges that project framework templates into the vanilla element via slot-based portals
  • No legacy — no $scope, no Bower, no Grunt, no jQuery, no module system from 2013

Feature Comparison

Everything below ships free and MIT-licensed. No enterprise tier, no license keys, no per-developer fees.

FeatureUI Gridag-Grid Communityag-Grid EnterpriseVaadin GridKendo UISyncfusion
SortingFreeFreeFreePaidCommunity*
FilteringFreeFreeFreePaidCommunity*
Row GroupingFree~$999/dev/yrPaidCommunity*
Tree DataFree~$999/dev/yrFreePaidCommunity*
Master/Detail RowsFree~$999/dev/yrPaidCommunity*
Inline Cell EditingFreeFreePro ~$159/dev/moPaidCommunity*
Row SelectionFreeFreeFreePaidCommunity*
Column ResizingFreeFreeFreePaidCommunity*
CSV ExportFreeFreePaidCommunity*
Excel ExportFree~$999/dev/yrPaidCommunity*
PDF ExportFree~$999/dev/yrPaidCommunity*
Virtual ScrollingFreeFreeFreePaidCommunity*
PaginationFreeFreeFreePaidCommunity*
Column PinningFreeFreeFreePaidCommunity*
Column ReorderingFreeFreeFreePaidCommunity*
Save/Restore StateFreeFreePaid
Infinite ScrollFreeFreeFreePaidCommunity*
Keyboard Cell NavFreeFreePaidCommunity*
Row Edit (dirty/save)Free
Cell ValidationFree
CSV/JSON ImportFree
Shadow DOMFree
Web Component BuildFreeNative
Feature Tree-ShakingFree
SSR SupportFree~$999/dev/yr
i18n (6 locales built-in)FreeFreeFreePaidCommunity*
ReactYesWrapperWrapperNoWrapperWrapper
Rust/egui NativeYesNoNoNoNoNo
C/LVGL NativeYesNoNoNoNoNo
AngularYesWrapperWrapperNoWrapperWrapper
LicenseMITMITCommercialApache/Comm.CommercialComm./Community
Price$0$0~$999/dev/yr$159/dev/mo (Pro)~$799/dev/yrSee below

Bold = features where UI Grid gives you for free what competitors charge for or don't offer at all.

Syncfusion Community license is free for companies with <$1M annual revenue, ≤5 developers, and ≤$3M outside capital. Their paid tier requires a custom quote. Kendo UI ranges $799–$1,299/dev/yr depending on support level. Prices are approximate and subject to change.


Quick Start

npm install @ornery/ui-grid

Angular Component

import { Component } from '@angular/core';
import { GridOptions, UiGridComponent } from '@ornery/ui-grid';

@Component({
  selector: 'app-my-grid',
  imports: [UiGridComponent],
  template: `<app-ui-grid [options]="gridOptions" />`,
})
export class MyGridComponent {
  gridOptions: GridOptions = {
    id: 'my-grid',
    data: [
      { name: 'Alice', role: 'Engineer', salary: 120000 },
      { name: 'Bob', role: 'Designer', salary: 95000 },
    ],
    columnDefs: [
      { name: 'name' },
      { name: 'role' },
      { name: 'salary', type: 'number', align: 'end' },
    ],
    onRegisterApi: (api) => {
      this.gridApi = api;
    },
  };
}

React

npm install @ornery/ui-grid-react @ornery/ui-grid-core @ornery/ui-grid-vanilla
import { UiGrid } from '@ornery/ui-grid-react';
import type { GridOptions } from '@ornery/ui-grid-core';

function MyGrid() {
  const options: GridOptions = {
    id: 'my-grid',
    data: [
      { name: 'Alice', role: 'Engineer', salary: 120000 },
      { name: 'Bob', role: 'Designer', salary: 95000 },
    ],
    columnDefs: [
      { name: 'name' },
      { name: 'role' },
      { name: 'salary', type: 'number', align: 'end' },
    ],
  };

  return <UiGrid options={options} />;
}

Web Components (Vanilla)

The grid's rendering engine is a framework-free custom element (<ui-grid-element>) built on @ornery/ui-grid-core with pure DOM rendering and Shadow DOM encapsulation. Both the Angular and React wrappers are thin bridges around this same element — they mount <ui-grid-element>, pass options, and project framework-specific templates into it via a slot-based portal system.

npm install @ornery/ui-grid-vanilla @ornery/ui-grid-core

Declarative HTML usage:

<ui-grid-element
  grid-id="vanilla-demo"
  title="Team Roster"
  enable-sorting
  enable-filtering
  column-defs='[
    { "name": "name" },
    { "name": "role" },
    { "name": "salary", "type": "number", "align": "end" }
  ]'
  data='[
    { "name": "Alice", "role": "Engineer", "salary": 120000 },
    { "name": "Bob", "role": "Designer", "salary": 95000 }
  ]'>
</ui-grid-element>

<script type="module">
  import { defineStandaloneUiGridElement } from '@ornery/ui-grid-vanilla';

  await defineStandaloneUiGridElement(); // registers <ui-grid-element>
</script>

Supported declarative inputs include boolean flags (enable-sorting, enable-filtering), scalar attributes (grid-id, title, row-height), and JSON attributes (column-defs, data).

For callbacks, function-valued column definitions, or high-frequency updates, use the options property:

import { mountVanillaUiGrid } from '@ornery/ui-grid-vanilla';

await mountVanillaUiGrid(document.getElementById('app'), {
  id: 'mounted-grid',
  data: [{ name: 'Alice', role: 'Engineer' }],
  columnDefs: [{ name: 'name' }, { name: 'role' }],
});

Native Rust / egui

[dependencies]
ui-grid-egui = "0.1"
ui-grid-core = "0.1"
use ui_grid_egui::{EguiColumnExt, EguiGrid, GridThemePreset};
use ui_grid_core::models::{GridColumnDef, GridOptions};

let mut grid = EguiGrid::new();
let theme = GridThemePreset::DefaultDark.build();
let mut column_ext: Vec<EguiColumnExt> = vec![];

// Each frame, inside your egui UI:
grid.show(ui, &mut options, &columns, &mut column_ext, &theme);

To run the interactive demo app locally:

git clone https://github.com/orneryd/uiGrid.git
cd uiGrid
cargo run -p ui-grid-egui --example demo --release

See docs/rust-egui.md for pinning, CSV export, save/restore state, and custom column extensions.

Native C / LVGL

The C adapter sits on top of the same Rust core and C ABI contract used by the other foreign bindings. The current demo uses LVGL with the SDL desktop backend.

Prerequisites:

  • Rust 1.95+
  • CMake 3.20+
  • SDL2
brew install sdl2
cargo build -p ui-grid-c-abi
cmake -S crates/ui-grid-lvgl -B target/ui-grid-lvgl
cmake --build target/ui-grid-lvgl -j4
./target/ui-grid-lvgl/ui-grid-lvgl-demo

The LVGL demo currently exercises the native C grid shell with sorting, grouping, pinning, state save/restore, theme presets, live trading-row updates, and the shared projection/command contract.


Features

  • Sorting — click column headers to cycle asc/desc/none, custom comparators, programmatic API
  • Filtering — per-column inputs with conditions: contains, exact, startsWith, endsWith, greaterThan, regex, custom predicates
  • Row Grouping — nested multi-column grouping with collapsible group headers
  • Tree View — hierarchical data with expand/collapse per node, arbitrary nesting depth
  • Expandable Rows — master/detail pattern with custom templates (Angular ng-template, React render prop, or vanilla <template> slot)
  • Cell Editing — inline spreadsheet-style editing with full keyboard navigation (Tab, Enter, Escape), edit-on-focus, Enter/Tab commit+move across editable columns
  • Keyboard Cell Navigation — Arrow/Tab/Home/End navigation with wrap/clamp modes, focus persistence across re-renders, keyDownOverrides for custom key handling, full gridApi.cellNav surface
  • Row Selection — click/shift/ctrl/drag-paint mouse selection, keyboard (Space, Ctrl+A), row-header checkbox column, select-all header, isRowSelectable hook, 13 options, 18 API methods, 3 events
  • Column Resizing — drag column borders to resize, programmatic API, persisted via save/restore state
  • Row Edit — dirty/saving/error row lifecycle with rowEditWaitInterval debounce, setSavePromise pattern, auto-retry on error, visual row state indicators
  • Cell Validation — declarative per-column validators (built-in required, minLength, maxLength + custom), async validator support, invalid cell markers with error messages, gridApi.validate surface
  • Pagination — client-side or external pagination with configurable page sizes
  • Infinite Scroll — bi-directional infinite scrolling with loading state management, needLoadMoreData/needLoadMoreDataTop events, full public API
  • Column Pinning — freeze columns left or right with CSS position: sticky, programmatic API, save/restore state
  • Column Moving — HTML5 native drag-and-drop column reordering
  • CSV Export — download visible/selected/all rows with formula-injection protection, full option matrix (separator, header filter, field callbacks, BOM compatibility)
  • Excel Export — ExcelBuilder-compatible sheet data with native numeric/boolean types preserved, configurable filename/sheet/header/custom formatters
  • PDF Export — pdfMake-ready document definition with orientation/page size/styles/header/footer/custom formatter, auto-download when pdfMake is available
  • CSV/JSON Import — file picker or programmatic import, full CSV parser (quoted values, escaped quotes, CRLF), header-to-column mapping, integrates with row-edit for dirty marking
  • Export/Import MenubuildGridExporterMenuItems() with per-format and per-scope flags, i18n-driven menu labels
  • Virtual Scrolling — virtual scroll viewport, auto-enabled at 40+ rows
  • Save/Restore State — serialize and restore sort, filters, grouping, collapsed groups, pinning, column order, column widths, pagination, selection, focused cell, tree/expandable expansion, and scroll position (per-field opt-in flags)
  • Native Rust and C Grids — shared Rust core with native Rust/egui and native C/LVGL adapters driven by the same projection and command contract
  • Auto Resize — ResizeObserver-driven viewport height recalculation
  • Custom Cell Templates — Angular ng-template, React cellRenderers map (per-column render functions), vanilla <template> slots with slot-based portal projection
  • Shadow DOM — encapsulated styles with CSS custom property and ::part() hooks
  • Web Component — ships as <ui-grid-element>, a framework-free vanilla custom element (@ornery/ui-grid-vanilla); Angular and React wrappers mount this same element and project templates into it
  • Feature-Flag Builds — compile-time tree-shaking of unused features
  • i18n — 6 locales built-in (English, Spanish, French, German, Japanese, Simplified Chinese), runtime gridApi.i18n for language switching, fallback chain (options.labels → current locale → en-US), register additional locales via gridApi.i18n.add()
  • SSR Support — server-side rendering with platform-safe guards

Theming

The grid renders inside Shadow DOM. Customize it via the public --ui-grid-* CSS custom properties:

.my-app {
  --ui-grid-surface: #1e1b2e;
  --ui-grid-accent: #8b5cf6;
  --ui-grid-header-background: #2d2640;
  --ui-grid-cell-color: #e2e0f0;
  --ui-grid-border-color: rgba(139, 92, 246, 0.2);
  --ui-grid-row-hover: #322e4a;
}

Legacy --app-ui-grid-* aliases remain supported as a fallback for older app themes, but new consumer theming should target only --ui-grid-*.

Target structural elements with ::part():

app-ui-grid::part(header) {
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

See docs/theming.md for the full CSS variable reference grouped by grid section, ::part() hooks, and the demo app's 4-mode theme system.


Custom Builds

Ship only the features you use:

# Only sorting and filtering — everything else is tree-shaken
node scripts/build-grid.mjs --features sorting,filtering

# Bake in a locale at build time
node scripts/build-grid.mjs --features sorting,filtering,pagination --locale i18n/fr-FR.json

# See all available flags
node scripts/build-grid.mjs --list

See docs/custom-builds.md for the full feature flag table and build presets.


Documentation

GuideDescription
Getting StartedInstall, minimal setup, run the demo
FeaturesOverview of all features with code examples
ThemingCSS custom properties, ::part() hooks, sample themes
API ReferenceGridOptions, GridColumnDef, UiGridApi
Cell EditingKeyboard navigation, conditional editing, API
Tree ViewHierarchical data, options, API
Expandable RowsMaster/detail, template context, API
Custom BuildsFeature flags, build presets, locale baking
Web ComponentVanilla <ui-grid-element> custom element usage
InternationalizationRuntime overrides, build-time locales
AccessibilityARIA roles, keyboard navigation, screen reader support
Rust / WASMRust pipeline in Angular, React, and vanilla hosts
Rust / eguiNative egui adapter with pinning, export, save/restore
README native C / LVGL sectionNative C/LVGL build and demo run instructions

Interactive versions of all documentation are also available in the live demo.


Development

npm start          # Dev server at localhost:4200
npm test           # Run tests (Vitest)
npm run build      # Production build
npm run build:library   # Build the library (ng-packagr)
npm run build:rust:web  # Build the browser-native Rust/WASM artifact
npm run start:vanilla   # Run the Rust-backed browser demo at 127.0.0.1:4174

Rust / egui

Requires Rust 1.95+.

cargo test --workspace                                    # Run all Rust tests
cargo clippy --workspace --all-targets -- -D warnings     # Lint
cargo run -p ui-grid-egui --example demo --release        # Run the native egui demo app

C / LVGL

Requires SDL2 plus the Rust/C ABI build.

brew install sdl2
cargo build -p ui-grid-c-abi
cmake -S crates/ui-grid-lvgl -B target/ui-grid-lvgl
cmake --build target/ui-grid-lvgl -j4
./target/ui-grid-lvgl/ui-grid-lvgl-demo                  # Run the native C/LVGL demo app

Compatibility

DependencyVersion
Angular21.2
TypeScript5.9
RxJS7.8
Node22.20
npm11.11
Rust1.95+
egui0.34

Contributing

Contributions are welcome. Please open an issue first to discuss what you'd like to change.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/my-feature)
  3. Run npm test to ensure all tests pass
  4. Submit a pull request

License

MIT