Pagination
OGrid includes a built-in pagination bar with page navigation buttons, page size selector, and a row count summary. It works seamlessly with both client-side data arrays and server-side data sources.
Live Demo
The live demo above shows React Radix UI styling (lightweight default). To see how pagination controls look in your framework's design system, click the framework buttons above the demo to open online demo. Each framework renders with its native button and dropdown components, so the styling matches your design system.
Quick Example
- React
- Angular
- Vue
- Vanilla JS
import { OGrid } from '@alaarab/ogrid-react-radix';
const columns = [
{ columnId: 'name', name: 'Name' },
{ columnId: 'email', name: 'Email' },
{ columnId: 'department', name: 'Department' },
{
columnId: 'salary',
name: 'Salary',
type: 'numeric' as const,
valueFormatter: (v) => `$${Number(v).toLocaleString()}`,
},
];
function App() {
return (
<OGrid
columns={columns}
data={people}
getRowId={(item) => item.id}
defaultPageSize={5}
pageSizeOptions={[5, 10, 25, 50]}
entityLabelPlural="people"
/>
);
}
The OGrid component has the same props across all React UI packages. To switch, just change the import:
- Radix (lightweight, default):
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';
@Component({
standalone: true,
imports: [OGridComponent],
template: `<ogrid [props]="gridProps" />`
})
export class GridComponent {
gridProps = {
columns: [
{ columnId: 'name', name: 'Name' },
{ columnId: 'email', name: 'Email' },
{ columnId: 'department', name: 'Department' },
{
columnId: 'salary', name: 'Salary', type: 'numeric',
valueFormatter: (v: unknown) => `$${Number(v).toLocaleString()}`,
},
] as IColumnDef<Person>[],
data: people,
getRowId: (item: Person) => item.id,
defaultPageSize: 5,
pageSizeOptions: [5, 10, 25, 50],
entityLabelPlural: 'people',
};
}
Same component API across Angular packages. To switch, just change the import:
- Radix (CDK):
from '@alaarab/ogrid-angular-radix'(default, lightweight) - 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';
const columns: IColumnDef<Person>[] = [
{ columnId: 'name', name: 'Name' },
{ columnId: 'email', name: 'Email' },
{ columnId: 'department', name: 'Department' },
{
columnId: 'salary', name: 'Salary', type: 'numeric',
valueFormatter: (v) => `$${Number(v).toLocaleString()}`,
},
];
const gridProps = {
columns,
data: people,
getRowId: (item) => item.id,
defaultPageSize: 5,
pageSizeOptions: [5, 10, 25, 50],
entityLabelPlural: 'people',
};
</script>
<template>
<OGrid :gridProps="gridProps" />
</template>
Same component API across Vue packages. To switch, just change the import:
- Radix (Headless UI):
from '@alaarab/ogrid-vue-radix'(default, lightweight) - 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' },
{ columnId: 'email', name: 'Email' },
{ columnId: 'department', name: 'Department' },
{
columnId: 'salary',
name: 'Salary',
type: 'numeric',
valueFormatter: (v) => `$${Number(v).toLocaleString()}`,
},
],
data: people,
getRowId: (item) => item.id,
pageSize: 5,
pageSizeOptions: [5, 10, 25, 50],
entityLabelPlural: 'people',
});
How It Works
Pagination is automatic. When your data exceeds the page size, the pagination bar appears at the bottom of the grid with:
- Previous / Next buttons
- Page number indicator ("Page 1 of 5")
- Page size selector (dropdown to change rows per page)
- Row count summary ("Showing 1-25 of 120 projects")
Client-Side Pagination
When you pass a data array, OGrid slices it automatically based on the current page and page size. Sorting and filtering are applied before slicing.
Server-Side Pagination
When you pass a dataSource, the grid calls fetchPage() with page and pageSize parameters. Your server returns only the rows for that page along with a totalCount:
const dataSource: IDataSource<Project> = {
fetchPage: async ({ page, pageSize, sort, filters }) => {
const res = await fetch(`/api/projects?page=${page}&pageSize=${pageSize}`);
const json = await res.json();
return { items: json.data, totalCount: json.total };
},
};
function App() {
return (
<OGrid
columns={columns}
dataSource={dataSource}
getRowId={(item) => item.id}
defaultPageSize={50}
entityLabelPlural="projects"
/>
);
}
Controlled Pagination
For full control over page state (e.g., URL-synced pagination), pass page, pageSize, onPageChange, and onPageSizeChange:
function App() {
const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(25);
return (
<OGrid
columns={columns}
data={items}
getRowId={(item) => item.id}
page={page}
pageSize={pageSize}
onPageChange={setPage}
onPageSizeChange={setPageSize}
/>
);
}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
defaultPageSize | number | 25 | Initial page size (uncontrolled mode). |
pageSizeOptions | number[] | [10, 25, 50, 100] | Options shown in the page size dropdown. If the active page size isn't in the list, it's auto-inserted. |
page | number | -- | Current page number (controlled mode, 1-indexed). |
pageSize | number | -- | Rows per page (controlled mode). |
onPageChange | (page: number) => void | -- | Called when page changes. |
onPageSizeChange | (size: number) => void | -- | Called when page size changes. |
entityLabelPlural | string | 'items' | Label used in the row count summary (e.g., "Showing 1-25 of 100 projects"). |