6. Adding Sort and Filters
In the previous Adding List Page section, we have displayed blog posts data in a table. Now we will learn how to add sorting and filtering to the table to user can have more control over the data.
Sort and Filters
The @pankod/refine-react-table
package based on the Tanstack Table package. So, we can add sorting and filtering features to our table as suggested in the Tanstack Table documentation.
Refer to the @pankod/refine-react-table useTable
documentation for more information →
Tanstack Table keeps the sorting
and filters
states in the useTable
hook. When we change the these states, the useTable
hook will automatically fetch the data and update the table with the new data.
Under the hood, sorting
and filters
states of Tanstack Table are converted to the CrudSorting
and CrudFilter
types of refine. So, when you change the Tanstack Table's sorting
or filters
state, useTable
hook will pass the converted params to the getList
method of the dataProvider
.
Since @pankod/refine-react-table
provides a headless solution, there are many ways to handle filtering and sorting. In this tutorial, we will show basic examples of how to add sorting and filtering to the table.
Adding Sorting
Let's add sorting to the table. We will add a clickable column header to the table. When the user clicks on the column header, the table will be sorted by the column.
Open the
src/pages/blog-posts/list.tsx
file on your editor.Replace the
<thead/>
element with the following code:src/pages/blog-posts/list.tsx<thead>
{getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th key={header.id}>
<div onClick={header.column.getToggleSortingHandler()}>
{!header.isPlaceholder &&
flexRender(
header.column.columnDef.header,
header.getContext(),
)}
{{
asc: " 🔼",
desc: " 🔽",
}[header.column.getIsSorted() as string] ?? null}
</div>
</th>
))}
</tr>
))}
</thead>In the above code, we have added a
onClick
event to the column header. When the user clicks on the column header, thegetToggleSortingHandler
method of the column will be called. This method will toggle the sorting state of the column.We have also added a arrow icon to the column header. The arrow icon will be displayed based on the sorting state of the column. If the column is not sorted, no icon will be displayed. If the column is sorted in ascending order, the
🔼
icon will be displayed. If the column is sorted in descending order, the🔽
icon will be displayed.
How can I disable sorting for a specific column?
You can disable sorting for a specific column by setting the enableSorting
property of the column to false
in the column definition like below.
{
title: "Category",
dataIndex: "category",
enableSorting: false,
},
Adding Filters
Let's add filters to the table. We will add a basic text input to the table header. When the user types in the input, the table will be filtered by the input value of the column.
Open the
src/pages/blog-posts/list.tsx
file on your editor.Change the filter operator for columns to "contains" by changing the
meta
property of the column definition like below:{
id: "title",
accessorKey: "title",
header: "Title",
meta: {
filterOperator: "contains",
},
},
{
id: "content",
accessorKey: "content",
header: "Content",
meta: {
filterOperator: "contains",
},
},By default, the
filterOperator
is set to "eq". So, we have changed thefilterOperator
to "contains" for specific columns.Disable filtering for the "Action" column by setting the
enableFiltering
property of the column tofalse
in the column definition like below:{
id: "actions",
accessorKey: "id",
header: "Actions",
enableColumnFilter: false,
cell: function render({ getValue }) {
return (
<div
style={{
display: "flex",
flexDirection: "row",
flexWrap: "wrap",
gap: "4px",
}}
>
<button
onClick={() => {
show("blog_posts", getValue() as string);
}}
>
Show
</button>
<button
onClick={() => {
edit("blog_posts", getValue() as string);
}}
>
Edit
</button>
</div>
);
},
},Replace the
<thead/>
element with the following code:<thead>
{getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th key={header.id}>
<div onClick={header.column.getToggleSortingHandler()}>
{!header.isPlaceholder &&
flexRender(
header.column.columnDef.header,
header.getContext(),
)}
{{
asc: " 🔼",
desc: " 🔽",
}[header.column.getIsSorted() as string] ?? null}
</div>
<div>
{header.column.getCanFilter() && (
<input
value={header.column.getFilterValue() as string}
onChange={(e) => {
header.column.setFilterValue(e.target.value);
}}
placeholder={`Search ${header.column.columnDef.header}`}
/>
)}
</div>
</th>
))}
</tr>
))}
</thead>In the above code, we have added a basic text input to the column header. When the user types in the input, the
setFilterValue
method of the column will be called. This method will set the filter value of the column.Previous step, we have also added a
enableColumnFilter
property to the column definition. This property will be used to determine whether the column should have a filter input or not by calling thegetCanFilter
method of the column.
How can I change the filter operator?
By default, filter operator is "eq" for columns. You can change the filter operator by passing the filterOperator
property to the meta
in column definition. For example, you can change the filter operator to "eq" like below:
{
title: "Category",
dataIndex: "category",
meta: {
filterOperator: "eq",
},
},
How can I disable filtering for a specific column?
You can disable filtering for a specific column by setting the enableColumnFilter
property of the column to false
in the column definition like below.
{
title: "Category",
dataIndex: "category",
enableColumnFilter: false,
},