List Search
We will examine how to make an extensive search and filtering with the useSimpleList
hook that works with the Ant Design's <List>
component.
To do this, let's list posts using the posts resource.
import { useMany } from "@pankod/refine-core";
import {
List,
useSimpleList,
AntdList,
Typography,
Space,
NumberField,
} from "@pankod/refine-antd";
const { Text } = Typography;
export const PostList: React.FC = () => {
const { listProps } = useSimpleList<IPost>();
const categoryIds =
listProps?.dataSource?.map((item) => item.category.id) ?? [];
const { data } = useMany<ICategory>({
resource: "categories",
ids: categoryIds,
queryOptions: {
enabled: categoryIds.length > 0,
},
});
const renderItem = (item: IPost) => {
const { title, hit, content } = item;
const categoryTitle = data?.data.find(
(category: ICategory) => category.id === item.category.id,
)?.title;
return (
<AntdList.Item
actions={[
<Space key={item.id} direction="vertical" align="end">
<NumberField
value={hit}
options={{
notation: "compact",
}}
/>
<Text>{categoryTitle}</Text>
</Space>,
]}
>
<AntdList.Item.Meta title={title} description={content} />
</AntdList.Item>
);
};
return (
<List>
<AntdList {...listProps} renderItem={renderItem} />
</List>
);
};
interface ICategory {
id: number;
title: string;
}
interface IPost {
id: number;
title: string;
content: string;
hit: number;
category: { id: number };
}
After creating the <PostList>
component, add it to the resource with list
prop:
import { Refine } from "@pankod/refine-core";
import {
Layout,
ReadyPage,
useNotificationProvider,
ErrorComponent,
} from "@pankod/refine-antd";
import routerProvider from "@pankod/refine-react-router-v6";
import dataProvider from "@pankod/refine-simple-rest";
import "@pankod/refine-antd/dist/reset.css";
import { PostList } from "pages/posts";
const API_URL = "https://api.fake-rest.refine.dev";
const App: React.FC = () => {
return (
<Refine
routerProvider={routerProvider}
dataProvider={dataProvider(API_URL)}
Layout={Layout}
ReadyPage={ReadyPage}
notificationProvider={useNotificationProvider}
catchAll={<ErrorComponent />}
resources={[
{
name: "posts",
list: PostList,
},
]}
/>
);
};
export default App;
We will create a form by extracting searchFormProps
from useSimpleList
. We will use this form for search/filtering. We will also create an interface to determine the types of values from the form.
...
import {
...
CrudFilters,
} from "@pankod/refine-core";
export const PostList: React.FC = () => {
const { listProps, searchFormProps } = useSimpleList<
IPost,
IPostFilterVariables
>({
onSearch: (params) => {
const filters: CrudFilters = [];
const { category, createdAt } = params;
filters.push(
{
field: "category.id",
operator: "eq",
value: category,
},
{
field: "createdAt",
operator: "gte",
value: createdAt ? createdAt[0].toISOString() : undefined,
},
{
field: "createdAt",
operator: "lte",
value: createdAt ? createdAt[1].toISOString() : undefined,
},
);
return filters;
},
});
// ...
const { selectProps: categorySelectProps } = useSelect<ICategory>({
resource: "categories",
});
return (
<List>
<Form
{...searchFormProps}
layout="vertical"
onValuesChange={() => searchFormProps.form?.submit()}
>
<Space wrap>
<Form.Item label="Category" name="category">
<Select
{...categorySelectProps}
allowClear
placeholder="Search Categories"
/>
</Form.Item>
<Form.Item label="Created At" name="createdAt">
<RangePicker />
</Form.Item>
</Space>
</Form>
<AntdList {...listProps} renderItem={renderItem} />
</List>
);
};
interface IPostFilterVariables {
category: string;
createdAt: [Dayjs, Dayjs];
}
When the form is submitted, the onSearch
method runs and we get the search form values. Then the listProps
is refreshed according to the criteria.
CrudFilters
type object has field
, operator
, and value
properties. These properties help us to filter in which field, with which operator, and with which data.
Example
npm create refine-app@latest -- --example use-simple-list-antd