Skip to content

Filtering & Sorting

Every CollectionView can have filters and sorts applied to it. The built-in UI provides filter/sort controls out of the box, but you can also configure them programmatically via transactions.

Filters use a tree structure that supports nesting:

// A single condition
interface FilterRule {
id: string;
propertyId: string; // which column to filter
operator: string; // e.g. "contains", "is", "greater_than"
value: string; // the value to compare against
}
// A group of conditions with AND/OR logic
interface FilterGroup {
id: string;
logicalOperator: "AND" | "OR";
children: Array<Filter>; // FilterRule or nested FilterGroup
}
// A filter is either a rule or a group
type Filter = FilterRule | FilterGroup;
const filter: FilterRule = {
id: "filter-1",
propertyId: "status",
operator: "is",
value: "done",
};

“Status is ‘done’ AND (priority > 2 OR assignee is ‘alice’)“:

const filter: FilterGroup = {
id: "filter-root",
logicalOperator: "AND",
children: [
{ id: "f1", propertyId: "status", operator: "is", value: "done" },
{
id: "f2",
logicalOperator: "OR",
children: [
{ id: "f3", propertyId: "priority", operator: "greater_than", value: "2" },
{ id: "f4", propertyId: "assignee", operator: "is", value: "alice" },
],
},
],
};

Use a transaction to update the view’s filters:

const manager = state.manager;
const view = manager.views[0];
manager.transaction.update(view, {
filters: [
{
id: "filter-1",
propertyId: "status",
operator: "is",
value: "done",
},
],
});

To clear all filters:

manager.transaction.update(view, { filters: undefined });

Sorts are an array of { property, desc } objects on the view:

const view = manager.views[0];
const statusProperty = manager.collection.schema["status"];
manager.transaction.update(view, {
sorts: [
{ property: statusProperty, desc: false }, // ascending
],
});

Multi-column sorting — sorts are applied in order:

const nameProperty = manager.collection.schema["name"];
const priorityProperty = manager.collection.schema["priority"];
manager.transaction.update(view, {
sorts: [
{ property: priorityProperty, desc: true }, // highest priority first
{ property: nameProperty, desc: false }, // then alphabetical
],
});

To clear sorts:

manager.transaction.update(view, { sorts: undefined });

Each property type has pre-defined operators:

Property typeAvailable operators
stringcontains, does_not_contain, is, is_not, starts_with, ends_with, is_empty, is_not_empty
numberequals, does_not_equal, greater_than, gte, less_than, lte, is_empty, is_not_empty
dateis, is_not, is_before, is_after, is_on_or_before, is_on_or_after, is_empty, is_not_empty
checkboxis, is_not
single-selectis, is_not, is_empty, is_not_empty
multi-selectis, is_not, contains, does_not_contain, is_empty, is_not_empty

Unary operators (is_empty, is_not_empty) don’t require a value in the filter rule.

The built-in <TableView> includes filter controls in the toolbar. Users can:

  1. Click the filter button in the actions toolbar
  2. Select a property, operator, and value
  3. Active filters appear as chips in the SortsFiltersToolbar
  4. Click a chip to edit the filter inline
  5. Remove individual filters or clear all

No extra code needed — this works out of the box with <TableView table={table} editable />.

When a view has active filters, new documents are automatically pre-populated with values that match the current filters. For example, if the view is filtered to status = "done", calling manager.createDocument() will create a document with status already set to "done".

This uses extractFilterCriteriaForNewDocument() internally. It works for deterministic, single-value filter rules (like is operators). Complex filters (OR groups, range operators) are skipped.

import type { CollectionManager } from "@blocknote/block-view/core";
import {
useCollectionTableView,
defaultPropertyDefinitions,
TableView,
} from "@blocknote/block-view/react";
function FilteredTable({ manager }: { manager: CollectionManager }) {
const view = manager.views[0];
// Apply a filter on mount
manager.transaction.update(view, {
filters: [
{
id: "status-filter",
propertyId: "status",
operator: "is_not",
value: "done",
},
],
sorts: [{ property: manager.collection.schema["priority"], desc: false }],
});
const { table } = useCollectionTableView({
collectionManager: manager,
viewId: view.id,
propertyDefinitions: defaultPropertyDefinitions,
});
return <TableView table={table} editable />;
}

Users can then modify filters and sorts through the toolbar UI, and those changes persist through the transaction system.