Skip to main content

Filtering

OGrid supports four built-in filter types -- text, multiSelect, people, and date -- configured per column. Filters appear as popovers triggered from column headers.

Live Demo

Click the filter icon in a column header to filter
Live
Name
Department
Status
Salary
Alice Johnson
Engineering
Active
$50,000
Bob Smith
Marketing
Draft
$53,500
Carol Lee
Sales
Archived
$57,000
David Kim
Finance
Active
$60,500
Eve Torres
Operations
Draft
$64,000
Frank Wu
Engineering
Archived
$67,500
Grace Park
Marketing
Active
$71,000
Henry Adams
Sales
Draft
$74,500
Irene Costa
Finance
Archived
$78,000
Jack Rivera
Operations
Active
$81,500
Framework-Specific Styling

The live demo above shows React Radix UI styling (lightweight default). To see how filter popovers look in your framework's design system, click the framework buttons above the demo to open online demo. Each framework renders filter UI with its native components (dropdowns, inputs, date pickers, etc.), so the styling matches your design system.

Quick Example

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

const columns = [
{
columnId: 'name',
name: 'Name',
filterable: { type: 'text' },
},
{
columnId: 'department',
name: 'Department',
filterable: { type: 'multiSelect', filterField: 'department' },
},
{
columnId: 'status',
name: 'Status',
filterable: { type: 'multiSelect', filterField: 'status' },
},
{
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={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 the filterable property on a column definition to an IColumnFilterDef object. The type field determines the filter UI:

Text Filter

A simple text input. Filters rows where the column value contains the search string (case-insensitive).

{ columnId: 'name', name: 'Name', filterable: { type: 'text' } }

Multi-Select Filter

A checkbox list with Select All and Clear All buttons. Users pick one or more values to include.

{
columnId: 'status',
name: 'Status',
filterable: {
type: 'multiSelect',
filterField: 'status', // field to filter on (defaults to columnId)
optionsSource: 'static', // 'static' | 'api' | 'years'
options: ['Active', 'Draft', 'Archived'],
},
}

Options sources:

optionsSourceBehavior
'static'Uses the options array you provide.
'api'Calls dataSource.fetchFilterOptions(field) to load options dynamically.
'years'Auto-generates a year list (current year down, configurable via yearsCount).
(omitted)Client-side: unique values extracted from the data array. Server-side: uses 'api'.

People Filter

A search-as-you-type input that finds users via dataSource.searchPeople(query). Displays UserLike objects with name, email, and photo.

{
columnId: 'assignee',
name: 'Assignee',
filterable: { type: 'people' },
}
info

The people filter requires a dataSource with a searchPeople method. It is designed for directory lookups (e.g., Microsoft Graph, LDAP).

Date Filter

A date range picker with From and To date inputs. Filters rows where the column value falls within the specified range.

{
columnId: 'createdDate',
name: 'Created',
type: 'date',
filterable: { type: 'date' },
}
tip

Columns with type: 'date' automatically get date formatting, chronological sorting, and a native date input editor — no additional configuration needed.

Controlled vs. Uncontrolled

  • Uncontrolled -- the grid manages filter state internally. Filters reset when the component unmounts.
  • Controlled -- pass filters and onFiltersChange to own the filter state externally (e.g., for URL sync or persistence).
function App() {
const [filters, setFilters] = useState<IFilters>({
status: { type: 'multiSelect', value: ['Active'] },
name: { type: 'text', value: 'John' },
});

return (
<OGrid
columns={columns}
data={tasks}
getRowId={(item) => item.id}
filters={filters}
onFiltersChange={setFilters}
/>
);
}

Server-Side Filtering

When using a dataSource, filter values are passed to fetchPage() in the filters param. The grid does not filter client-side.

const dataSource: IDataSource<Task> = {
fetchPage: async ({ filters, page, pageSize, sort }) => {
const params = new URLSearchParams({ page: String(page), pageSize: String(pageSize) });
if (filters.status?.type === 'multiSelect') params.set('status', filters.status.value.join(','));
const res = await fetch(`/api/tasks?${params}`);
return res.json();
},
fetchFilterOptions: async (field) => {
const res = await fetch(`/api/tasks/filter-options/${field}`);
return res.json();
},
searchPeople: async (query) => {
const res = await fetch(`/api/users/search?q=${query}`);
return res.json();
},
};

Props

PropTypeDefaultDescription
filterableIColumnFilterDef--Set on IColumnDef. Defines filter type and options.
filterable.type'text' | 'multiSelect' | 'people' | 'date'--Filter UI type.
filterable.filterFieldstringcolumnIdField name used in the filter model.
filterable.optionsSource'api' | 'static' | 'years'autoWhere multi-select options come from.
filterable.optionsstring[]--Static options for multi-select.
filterable.yearsCountnumber--Number of years to generate for 'years' source.
filtersIFilters--Controlled filter state on OGrid.
onFiltersChange(filters: IFilters) => void--Called when filters change (controlled mode).