Use search on table
I have this component and a want to use the useTableSearch properties for get filtered result
message.txt12.27KB
useTable hook. The useTable hook provides search capabilities through its onSearch and searchFormProps properties. Here's how you can modify your component to implement search:useTable hook's search properties:tableProps and searchFormProps from the useTable hook.useTable hook, we define an onSearch function that returns an array of filter objects. In this case, we're filtering by the "name" field using the "contains" operator.Form component and spread the searchFormProps onto it.Table component uses the tableProps to handle the filtered data.onSearch function will be called, and the table will be updated with the filtered results.filters.mode: "off" in the useTable hook options.IProduct interface and table columns according to your actual data structure.FilterDropdown component from refine Ant Design Table Filtering (https://refine.dev/docs/ui-integrations/ant-design/hooks/use-table/#filtering).filters.mode is set to "off". To enable server-side filtering, you need to change this setting. Here's how you can modify your useTable hook:filters.mode to "server", you're telling refine to handle the filtering on the server side Filters Mode (https://refine.dev/docs/ui-integrations/ant-design/hooks/use-table/#filtersmode).filters.mode as "off" and use Ant Design's built-in filtering capabilities:filters and onFilter props to handle client-side filtering Client-side Filtering (https://refine.dev/docs/ui-integrations/ant-design/hooks/use-table/#how-can-i-handle-client-side-filtering).useForm hook. Here's how you can modify your code to achieve this:``
Key changes made:
1. Added a state variable searchField to track the selected search field type
2. Made the Select component controlled by binding it to the searchField state
3. Created an onSubmitSearch function that creates filters based on both the selected field and search value
4. Used onFinish from refine's useForm hook to pass the filters to the data provider
5. Wrapped your components in a form element and attached the handleSubmit` functionuseForm in refine, you need to make sure you've properly configured the form's action. The useForm hook accepts a refineCoreProps object where you can specify the action property to determine what type of request should be made.action: 'create' in the refineCoreProps object when using useFormaction: 'edit' which will perform a PATCH/PUT requestonFinish function from the refineCore object returned by useForm to submit your form datauseForm hook. Let me explain how to achieve this.useForm hook is primarily designed for creating or editing resources, which typically use POST, PUT, or PATCH requests. However, if you need to perform a GET request for search functionality, you should use a different approach.action: "list" with filters:useTable hook instead:useTable hook is better suited for search operations as it's designed to work with GET requests:useTable hook as it's specifically designed for listing and filtering data with GET requests Frequently Asked Questions.handleSubmit function from useForm to handle form submissionController from @refinedev/react-hook-form to connect the TextField to the form stateonSubmit function that uses setFilters to apply the search filterresetForm function to clear both the form and filtersgetDefaultFilter usage to properly retrieve existing filter values"I have find solution for my case: I can passinitialFilterwith undefined value andwill be use operator fromuseTableinitialFilter" GitHub Issue #1199
onSearchonSearchonSearchsearchFormPropssearchFormPropssearchFormPropstablePropstablePropsFormTablefilters.mode: "off"IProductFilterDropdownfilters.modefilters.modefilters.modeonFilterexport default function MembershipList() {
const {
handleSubmit,
reset,
register,
refineCore: { queryResult, onFinish },
} = useForm<HttpError>({
shouldUseNativeValidation: true,
refineCoreProps: {
resource: 'membership/subscribers',
action: 'create',
},
})
<Box mb={2}>
<Typography variant="h6">검색어</Typography>
<Grid container spacing={2}>
<Grid item xs={12} sm={2}>
<Select defaultValue="member_phone" fullWidth sx={{ height: 40 }}>
<MenuItem value="member_phone">회원 휴대폰번호</MenuItem>
<MenuItem value="member_name">회원 이름</MenuItem>
<MenuItem value="member_id">회원 아이디</MenuItem>
</Select>
</Grid>
<Grid item xs={12} sm={10}>
<TextField
{...register('q')}
label={'검색'}
placeholder={'회원 휴대폰번호, 회원 이름, 회원 아이디'}
margin="normal"
fullWidth
autoFocus
size="small"
variant="outlined"
sx={{ mt: 0, height: 40 }}
/>
</Grid>
</Grid>
</Box>
<Box display="flex" justifyContent="flex-end" width="100%">
<Button type="submit" variant="contained" sx={{ mr: 2 }}>
검색하기
</Button>
<Button type="button" variant="contained" color="secondary" onClick={() => resetForm()}>
초기화
</Button>``
Key changes made:
1. Added a state variable to track the selected search field type
2. Made the Select component controlled by binding it to the state
3. Created an function that creates filters based on both the selected field and search value
4. Used from refine's hook to pass the filters to the data provider
5. Wrapped your components in a form element and attached the refineCorePropsrefineCorePropsaction: 'create'action: 'edit'onFinishrefineCoreaction: "list" const { filters } = useTable({
resource: 'membership/subscribers',
queryOptions: {
enabled: !!dataGridProps?.rows,
},
})
const { control } = useForm<IGroupFilterVariables, HttpError, IGroupFilterVariables>({
defaultValues: getDefaultFilter('membership/subscribers', filters, 'eq'),
})
<form method="GET" onSubmit={}>
<Box mb={2}>
<Typography variant="h6">검색어</Typography>
<Grid container spacing={2}>
<Grid item xs={12} sm={2}>
<Select defaultValue="member_phone" fullWidth sx={{ height: 40 }}>
<MenuItem value="member_phone">회원 휴대폰번호</MenuItem>
<MenuItem value="member_name">회원 이름</MenuItem>
<MenuItem value="member_id">회원 아이디</MenuItem>
</Select>
</Grid>
<Grid item xs={12} sm={10}>
<TextField
label={'검색'}
placeholder={'회원 휴대폰번호, 회원 이름, 회원 아이디'}
margin="normal"
fullWidth
autoFocus
size="small"
variant="outlined"
sx={{ mt: 0, height: 40 }}
/>
</Grid>
</Grid>
</Box>
<Box display="flex" justifyContent="flex-end" width="100%">
<Button type="submit" variant="contained" sx={{ mr: 2 }}>
검색하기
</Button>
<Button type="button" variant="contained" color="secondary" onClick={() => resetForm()}>
초기화
</Button>
</Box>handleSubmitController@refinedev/react-hook-formresetFormgetDefaultFilterinitialFilterinitialFilterimport React from "react";
import { HttpError } from "@refinedev/core";
import { useTable } from "@refinedev/antd";
import { Button, Form, Input, Space, Table } from "antd";
export const ProductTable: React.FC = () => {
const { tableProps, searchFormProps } = useTable<
IProduct,
HttpError,
IProduct
>({
resource: "products",
onSearch: (values) => {
return [
{
field: "name",
operator: "contains",
value: values.name,
},
];
},
});
return (
<div style={{ padding: "4px" }}>
<h2>Products</h2>
<Form {...searchFormProps}>
<Space>
<Form.Item name="name">
<Input placeholder="Search by name" />
</Form.Item>
<Form.Item>
<Button htmlType="submit">Search</Button>
</Form.Item>
</Space>
</Form>
<Table {...tableProps} rowKey="id">
<Table.Column dataIndex="id" title="ID" />
<Table.Column dataIndex="name" title="Name" />
<Table.Column dataIndex="price" title="Price" />
</Table>
</div>
);
};
interface IProduct {
id: number;
name: string;
price: string;
}<Table.Column
dataIndex="title"
title="Title"
filterDropdown={(props) => (
<FilterDropdown {...props}>
<Input
placeholder="Search title"
onChange={(e) => props.setSelectedKeys(e.target.value ? [e.target.value] : [])}
/>
</FilterDropdown>
)}
/>const { tableProps, searchFormProps } = useTable<IProduct, HttpError, IProduct>({
resource: "products",
onSearch: (params) => {
const filters: CrudFilters = [];
const { q } = params;
filters.push(
{
field: "q",
operator: "eq",
value: q,
}
);
return filters;
},
filters: {
mode: "server", // This enables server-side filtering
},
});<Table.Column
dataIndex="status"
title="Status"
filters={[
{ text: "Published", value: "published" },
{ text: "Draft", value: "draft" },
{ text: "Rejected", value: "rejected" },
]}
onFilter={(value, record) => record.status === value}
/>const {
handleSubmit,
register,
refineCore: { onFinish },
} = useForm({
refineCoreProps: {
resource: 'your-resource',
action: 'create', // This will make it a POST request
},
});
// Then in your form submission handler
const onSubmit = (data) => {
onFinish(data);
};const {
refineCore: { onFinish },
} = useForm({
refineCoreProps: {
resource: 'membership/subscribers',
action: 'list', // This will use GET request
},
});
const onSubmitSearch = (data) => {
// Create filters based on your search criteria
const filters = [
{
field: searchField,
operator: "contains",
value: data.q,
},
];
// Pass the filters to refine's data provider
onFinish({ filters });
};const {
tableProps,
searchFormProps,
filters,
setFilters,
} = useTable({
resource: 'membership/subscribers',
onSearch: (values) => {
return [
{
field: searchField,
operator: "contains",
value: values.q,
},
];
},
});const handleFormSubmit = (e) => {
e.preventDefault(); // Prevent default POST submission
// Get form values
const searchValue = document.querySelector('input[name="q"]').value;
const searchField = document.querySelector('select').value;
// Manually trigger a GET request using refine's dataProvider
dataProvider.getList({
resource: 'membership/subscribers',
filters: [
{
field: searchField,
operator: "contains",
value: searchValue,
},
],
}).then((result) => {
// Handle the search results
console.log(result.data);
});
};const mapOperator = (operator) => {
switch (operator) {
case "contains":
return "_like";
case "eq":
default:
return "";
}
};