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,
notificationProvider,
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={notificationProvider}
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