Quick Start
Here's a grid in 60 seconds — sorting, filtering, editing, pagination, and keyboard navigation, all working out of the box.
Install
Pick your framework and UI library:
- React
- Angular
- Vue
- Vanilla JS
- Radix (Default)
- Fluent UI
- Material UI
npm install @alaarab/ogrid-react-radix
npm install @alaarab/ogrid-react-fluent @fluentui/react-components
npm install @alaarab/ogrid-react-material @mui/material @emotion/react @emotion/styled
- Angular Material
- PrimeNG
npm install @alaarab/ogrid-angular-material @angular/material @angular/cdk
npm install @alaarab/ogrid-angular-primeng primeng
- Vuetify
- PrimeVue
npm install @alaarab/ogrid-vue-vuetify vuetify
npm install @alaarab/ogrid-vue-primevue primevue
npm install @alaarab/ogrid-js
Your first grid
This example renders an employee directory with sortable columns, a department filter, and an editable salary column. Copy it and it'll just work.
- React
- Angular
- Vue
- Vanilla JS
import { OGrid, type IColumnDef } from '@alaarab/ogrid-react-radix';
interface Employee {
id: number;
name: string;
department: string;
salary: number;
}
const data: Employee[] = [
{ id: 1, name: 'Alice Johnson', department: 'Engineering', salary: 95000 },
{ id: 2, name: 'Bob Smith', department: 'Marketing', salary: 72000 },
{ id: 3, name: 'Carol Williams', department: 'Engineering', salary: 110000 },
{ id: 4, name: 'David Brown', department: 'Sales', salary: 68000 },
{ id: 5, name: 'Eva Martinez', department: 'Marketing', salary: 78000 },
];
const columns: IColumnDef<Employee>[] = [
{ columnId: 'name', name: 'Name', sortable: true },
{
columnId: 'department',
name: 'Department',
sortable: true,
filterable: { type: 'multiSelect', options: ['Engineering', 'Marketing', 'Sales'] },
},
{
columnId: 'salary',
name: 'Salary',
type: 'numeric',
sortable: true,
editable: true,
valueFormatter: (value) =>
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(value as number),
},
];
export default function App() {
return (
<OGrid<Employee>
columns={columns}
data={data}
getRowId={(row) => row.id}
defaultPageSize={10}
defaultSortBy="name"
statusBar
aria-label="Employee directory"
/>
);
}
The OGrid component has identical props across all React UI packages. To switch, change one import:
- Radix (lightweight, no peer deps):
from '@alaarab/ogrid-react-radix' - Fluent UI (Microsoft 365 / SPFx):
from '@alaarab/ogrid-react-fluent'- wrap in<FluentProvider> - Material UI (MUI v7):
from '@alaarab/ogrid-react-material'- wrap in<ThemeProvider>
import { Component } from '@angular/core';
import { OGridComponent, type IColumnDef } from '@alaarab/ogrid-angular-material';
interface Employee {
id: number;
name: string;
department: string;
salary: number;
}
@Component({
standalone: true,
imports: [OGridComponent],
template: `<ogrid [props]="gridProps" />`
})
export class EmployeeGridComponent {
private readonly data: Employee[] = [
{ id: 1, name: 'Alice Johnson', department: 'Engineering', salary: 95000 },
{ id: 2, name: 'Bob Smith', department: 'Marketing', salary: 72000 },
{ id: 3, name: 'Carol Williams', department: 'Engineering', salary: 110000 },
{ id: 4, name: 'David Brown', department: 'Sales', salary: 68000 },
{ id: 5, name: 'Eva Martinez', department: 'Marketing', salary: 78000 },
];
private readonly columns: IColumnDef<Employee>[] = [
{ columnId: 'name', name: 'Name', sortable: true },
{
columnId: 'department', name: 'Department', sortable: true,
filterable: { type: 'multiSelect', options: ['Engineering', 'Marketing', 'Sales'] },
},
{
columnId: 'salary', name: 'Salary', type: 'numeric', sortable: true, editable: true,
valueFormatter: (value) =>
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(value as number),
},
];
gridProps = {
columns: this.columns,
data: this.data,
getRowId: (row: Employee) => row.id,
defaultPageSize: 10,
defaultSortBy: 'name',
statusBar: true,
};
}
All Angular packages share the same component API. Change one import:
- Radix (CDK) (lightweight):
from '@alaarab/ogrid-angular-radix' - Angular Material:
from '@alaarab/ogrid-angular-material' - PrimeNG:
from '@alaarab/ogrid-angular-primeng'
All components are standalone — no NgModule required.
<script setup lang="ts">
import { OGrid, type IColumnDef } from '@alaarab/ogrid-vue-vuetify';
interface Employee {
id: number;
name: string;
department: string;
salary: number;
}
const data: Employee[] = [
{ id: 1, name: 'Alice Johnson', department: 'Engineering', salary: 95000 },
{ id: 2, name: 'Bob Smith', department: 'Marketing', salary: 72000 },
{ id: 3, name: 'Carol Williams', department: 'Engineering', salary: 110000 },
{ id: 4, name: 'David Brown', department: 'Sales', salary: 68000 },
{ id: 5, name: 'Eva Martinez', department: 'Marketing', salary: 78000 },
];
const columns: IColumnDef<Employee>[] = [
{ columnId: 'name', name: 'Name', sortable: true },
{
columnId: 'department', name: 'Department', sortable: true,
filterable: { type: 'multiSelect', options: ['Engineering', 'Marketing', 'Sales'] },
},
{
columnId: 'salary', name: 'Salary', type: 'numeric', sortable: true, editable: true,
valueFormatter: (value) =>
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(value as number),
},
];
const gridProps = {
columns,
data,
getRowId: (row: Employee) => row.id,
defaultPageSize: 10,
defaultSortBy: 'name',
statusBar: true,
};
</script>
<template>
<OGrid :gridProps="gridProps" />
</template>
All Vue packages share the same API. Change one import:
- Radix (Headless UI) (lightweight):
from '@alaarab/ogrid-vue-radix' - Vuetify:
from '@alaarab/ogrid-vue-vuetify'- wrap in<v-app>for theming - PrimeVue:
from '@alaarab/ogrid-vue-primevue'
import { OGrid } from '@alaarab/ogrid-js';
import '@alaarab/ogrid-js/styles';
const grid = new OGrid(document.getElementById('grid'), {
columns: [
{ columnId: 'name', name: 'Name', sortable: true },
{
columnId: 'department',
name: 'Department',
sortable: true,
filterable: { type: 'multiSelect', options: ['Engineering', 'Marketing', 'Sales'] },
},
{
columnId: 'salary',
name: 'Salary',
type: 'numeric',
sortable: true,
editable: true,
valueFormatter: (value) =>
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(value),
},
],
data: [
{ id: 1, name: 'Alice Johnson', department: 'Engineering', salary: 95000 },
{ id: 2, name: 'Bob Smith', department: 'Marketing', salary: 72000 },
{ id: 3, name: 'Carol Williams', department: 'Engineering', salary: 110000 },
{ id: 4, name: 'David Brown', department: 'Sales', salary: 68000 },
{ id: 5, name: 'Eva Martinez', department: 'Marketing', salary: 78000 },
],
getRowId: (row) => row.id,
pageSize: 10,
editable: true,
});
The JS package has a class-based imperative API. See the Vanilla JS guide for events, grid methods, and theming.
What you get for free
Paste those ~40 lines and you have:
- Sorting — click any column header, ascending/descending, shift-click for multi-sort
- Filtering — the Department column gets a multi-select dropdown filter
- Inline editing — double-click any salary cell to edit in place
- Currency formatting —
valueFormatterformats numbers on display without affecting stored values - Pagination, keyboard nav, cell selection, status bar — all there, no extra config
Three concepts worth knowing
| Description | |
|---|---|
IColumnDef<T> | Describes a column. columnId must match a key on your row type (or use valueGetter for computed values). |
getRowId | Returns a stable unique identifier per row. Used for selection, editing, and efficient re-renders. |
layoutMode | 'fill' (default) stretches the grid to fill its container. 'content' sizes to the data. |
Programmatic control
Need to interact with the grid from outside? Use the API:
- React
- Angular
- Vue
- Vanilla JS
import { useRef } from 'react';
import { OGrid, type IOGridApi } from '@alaarab/ogrid-react-radix';
function App() {
const gridRef = useRef<IOGridApi<Employee>>(null);
return (
<>
<button onClick={() => gridRef.current?.exportToCsv('employees.csv')}>
Export CSV
</button>
<OGrid<Employee> ref={gridRef} columns={columns} data={data} getRowId={(row) => row.id} />
</>
);
}
import { Component } from '@angular/core';
import { OGridComponent, OGridService } from '@alaarab/ogrid-angular-material';
@Component({
standalone: true,
imports: [OGridComponent],
template: `
<button (click)="exportCsv()">Export CSV</button>
<ogrid [props]="gridProps" />
`
})
export class AppComponent {
constructor(private gridService: OGridService) {}
exportCsv() {
this.gridService.exportToCsv('employees.csv');
}
gridProps = { columns, data, getRowId: (row: any) => row.id };
}
<script setup lang="ts">
import { OGrid, useOGrid } from '@alaarab/ogrid-vue-vuetify';
const { exportToCsv } = useOGrid({ columns, data, getRowId: (row) => row.id });
</script>
<template>
<button @click="exportToCsv('employees.csv')">Export CSV</button>
<OGrid :gridProps="{ columns, data, getRowId: (row) => row.id }" />
</template>
import { OGrid } from '@alaarab/ogrid-js';
const grid = new OGrid(document.getElementById('grid'), {
columns, data, getRowId: (row) => row.id,
});
document.getElementById('export-btn').addEventListener('click', () => {
grid.api.exportToCsv('employees.csv');
});
// Cleanup when done
grid.destroy();
What's next?
- Sorting, Filtering, Editing — dig into individual features
- Server-Side Data — connect to a REST API or GraphQL endpoint
- Grid API — full reference for programmatic control
- Column Definitions — every column option explained