Skip to main content

Sorting

Add sortable columns to your grid with a single prop. Users click a column header to cycle through ascending, descending, and unsorted states. A sort indicator arrow shows the current direction.

Live Demo

Click any column header to sort
Live
Name
Age
Department
Salary
Alice Johnson
25
Engineering
$50,000
Bob Smith
26
Marketing
$53,500
Carol Lee
27
Sales
$57,000
David Kim
28
Finance
$60,500
Eve Torres
29
Operations
$64,000
Frank Wu
30
Engineering
$67,500
Grace Park
31
Marketing
$71,000
Henry Adams
32
Sales
$74,500
Irene Costa
33
Finance
$78,000
Jack Rivera
34
Operations
$81,500
Try it in your framework

The demo above uses Radix UI for styling. To see this feature with your framework's design system (Fluent UI, Material UI, Vuetify, PrimeNG, etc.), click "Open in online demo" below the demo.

Quick Example

import { OGrid } from '@alaarab/ogrid-react-radix';

const columns = [
{ columnId: 'name', name: 'Name', sortable: true },
{ columnId: 'age', name: 'Age', sortable: true, type: 'numeric' as const },
{ columnId: 'department', name: 'Department', sortable: true },
{
columnId: 'salary',
name: 'Salary',
sortable: true,
type: 'numeric' as const,
valueFormatter: (v) => `$${Number(v).toLocaleString()}`,
},
];

function App() {
return (
<OGrid
columns={columns}
data={people}
getRowId={(item) => item.id}
defaultPageSize={10}
/>
);
}
Switching UI libraries

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>

How It Works

Set sortable: true on any column definition to make it sortable. When a user clicks the column header, OGrid toggles the sort direction: unsorted, ascending, then descending.

OGrid supports both uncontrolled and controlled sorting:

  • Uncontrolled -- the grid manages sort state internally. Use defaultSortBy and defaultSortDirection to set the initial sort.
  • Controlled -- you own the state. Pass sort and onSortChange to the grid.

Custom Comparator

For columns that need custom sort logic (e.g., sorting by a nested field or special ordering), provide a compare function on the column definition:

const columns = [
{
columnId: 'priority',
name: 'Priority',
sortable: true,
compare: (a, b) => {
const order = { High: 0, Medium: 1, Low: 2 };
return order[a.priority] - order[b.priority];
},
},
];

Server-Side Sorting

When using a dataSource, the sort parameter is forwarded to fetchPage(). The grid does not sort the data itself -- your server handles it:

const dataSource: IDataSource<Project> = {
fetchPage: async ({ sort, page, pageSize, filters }) => {
const res = await fetch(`/api/projects?sort=${sort?.field}&dir=${sort?.direction}&page=${page}`);
const json = await res.json();
return { items: json.data, totalCount: json.total };
},
};

Controlled Example

function App() {
const [sort, setSort] = useState({ field: 'name', direction: 'asc' as const });

return (
<OGrid
columns={columns}
data={people}
getRowId={(item) => item.id}
sort={sort}
onSortChange={setSort}
/>
);
}

Props

PropTypeDefaultDescription
sortablebooleanfalseSet on IColumnDef to enable sorting for that column.
compare(a: T, b: T) => number--Custom sort comparator on IColumnDef.
sort{ field: string; direction: 'asc' | 'desc' }--Controlled sort state on OGrid.
onSortChange(sort: { field: string; direction: 'asc' | 'desc' }) => void--Called when sort changes (controlled mode).
defaultSortBystring--Initial sort column (uncontrolled mode).
defaultSortDirection'asc' | 'desc''asc'Initial sort direction (uncontrolled mode).