A fully open-source, high-performance data grid with zero runtime dependencies. One engine, every framework.
Everything you need in a data grid, nothing you don't.
Both axes virtualized. Handles millions of rows at 60 fps with a tiny DOM footprint.
Click to sort. Ctrl+click to add secondary sorts. Three-state cycle: asc, desc, off.
Type >50000, 2020..2023, or ^Alice directly into the filter row. No dropdowns needed.
Click+drag for ranges. Ctrl+drag to add or remove. Supports both row and cell selection modes.
CSS custom properties with automatic OS detection. Override with one class toggle.
Pure vanilla TypeScript core. No bloat, no supply-chain risk, no version conflicts.
Cell-level selection with Excel-style ranges, row headers, keyboard navigation, and A1-notation coordinates.
Extend with custom cell renderers, filter logic, and event handlers without forking.
Thin wrappers around the same engine. Pick your framework.
npm install @ultimate-grid/coreimport { createGrid } from '@ultimate-grid/core'; import '@ultimate-grid/core/styles/ugrid.css'; const api = createGrid({ container: document.getElementById('grid'), columnDefs: [ { key: 'name', field: 'name', headerName: 'Name' }, { key: 'salary', field: 'salary', headerName: 'Salary' }, { key: 'joined', field: 'joined', headerName: 'Joined' }, ], rowData: [ { name: 'Alice', salary: 95000, joined: '2020-03-01' }, { name: 'Bob', salary: 72000, joined: '2018-07-15' }, ], selectionMode: 'multi', }); // API methods api.setSortModel([{ colId: 'name', direction: 'asc' }]); api.setFilterModel({ salary: { value: '>80000' } });
npm install @ultimate-grid/core @ultimate-grid/reactimport { UltimateGrid } from '@ultimate-grid/react'; import '@ultimate-grid/core/styles/ugrid.css'; function App() { const [gridApi, setGridApi] = useState(null); return ( <UltimateGrid columnDefs={columnDefs} rowData={rowData} selectionMode="multi" rowHeight={36} cellRenderer={customRenderer} onGridReady={(api) => setGridApi(api)} onSortChanged={handleSort} onFilterChanged={handleFilter} onSelectionChanged={handleSelection} /> ); }
npm install @ultimate-grid/core @ultimate-grid/vue<script setup> import { UltimateGrid } from '@ultimate-grid/vue'; import '@ultimate-grid/core/styles/ugrid.css'; const columnDefs = [/* ... */]; const rowData = ref([/* ... */]); function onGridReady(api) { // Store api reference } </script> <template> <UltimateGrid :column-defs="columnDefs" :row-data="rowData" selection-mode="multi" :row-height="36" @grid-ready="onGridReady" @sort-changed="onSortChanged" @filter-changed="onFilterChanged" @selection-changed="onSelectionChanged" /> </template>
npm install @ultimate-grid/core @ultimate-grid/svelte<script lang="ts"> import UltimateGrid from '@ultimate-grid/svelte'; import '@ultimate-grid/core/styles/ugrid.css'; let gridApi = null; const columnDefs = [/* ... */]; let rowData = [/* ... */]; </script> <UltimateGrid {columnDefs} {rowData} selectionMode="multi" rowHeight={36} onGridReady={(api) => gridApi = api} onSortChanged={handleSort} onFilterChanged={handleFilter} onSelectionChanged={handleSelection} />
npm install @ultimate-grid/core @ultimate-grid/angularimport { UltimateGridComponent } from '@ultimate-grid/angular'; import '@ultimate-grid/core/styles/ugrid.css'; @Component({ standalone: true, imports: [UltimateGridComponent], template: ` <ultimate-grid [columnDefs]="columnDefs" [rowData]="rowData" selectionMode="multi" [rowHeight]="36" [cellRenderer]="cellRenderer" (gridReady)="onGridReady($event)" (sortChanged)="onSortChanged($event)" (filterChanged)="onFilterChanged($event)" (selectionChanged)="onSelectionChanged($event)" /> `, }) export class AppComponent { columnDefs = [/* ... */]; rowData = [/* ... */]; }
npm install @ultimate-grid/core @ultimate-grid/angularjs// Register the module angular.module('myApp', ['ultimateGrid']) // In your template: <ultimate-grid column-defs="vm.columnDefs" row-data="vm.rowData" options="vm.gridOptions" selection-mode="multi" on-grid-ready="vm.onGridReady(api)" api="vm.gridApi"> </ultimate-grid> // Events broadcast to $rootScope: $rootScope.$on('ugrid:selectionChanged', function(_, e) { // No $scope.$apply() needed — digest-safe vm.selected = e.selectedRowIds.length; });
Install the core and your framework wrapper of choice.
git clone https://github.com/harvey-withington/ultimate-grid.git cd ultimate-grid npm install npm run dev
npm install @ultimate-grid/core # Framework wrappers (pick one) npm install @ultimate-grid/react npm install @ultimate-grid/vue npm install @ultimate-grid/svelte npm install @ultimate-grid/angular npm install @ultimate-grid/angularjs
npm run dev # Core (Vanilla JS) npm run dev:react # React npm run dev:vue # Vue 3 npm run dev:svelte # Svelte npm run dev:angular # Angular 17+ npm run dev:angularjs # AngularJS 1.x