ambitious-aqua
ambitious-aqua7mo ago

Use search on table

I have this component and a want to use the useTableSearch properties for get filtered result
21 Replies
kapa.ai
kapa.ai7mo ago
Hi @Sebastos. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Certainly! I can help you with using the search functionality on a table using refine's 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:
import 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;
}
import 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;
}
This example demonstrates how to use the useTable hook's search properties: 1. We destructure tableProps and searchFormProps from the useTable hook. 2. In the 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. 3. We create a form using Ant Design's Form component and spread the searchFormProps onto it. 4. Inside the form, we add an input field for the search term and a submit button. 5. The Table component uses the tableProps to handle the filtered data. When the user enters a search term and submits the form, the onSearch function will be called, and the table will be updated with the filtered results. This implementation allows for server-side filtering. If you want to handle client-side filtering instead, you can set filters.mode: "off" in the useTable hook options. Learn more about useTable and search (https://refine.dev/docs/ui-integrations/ant-design/hooks/use-table/#search) Remember to adjust the IProduct interface and table columns according to your actual data structure. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai7mo ago
<@689846866837373077> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
ambitious-aqua
ambitious-aquaOP7mo ago
@kapa.ai but I am using Antd protable, and with this config the search is not triggered
ambitious-aqua
ambitious-aquaOP7mo ago
@kapa.ai I have this component and the search from columns is not working. Also the filter is local and not in the server
kapa.ai
kapa.ai7mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I understand you're having issues with the search functionality in your table columns and that the filtering is happening locally instead of on the server. Let's address these problems based on the information provided in the knowledge sources. 1. Column Search Not Working: If the search from columns is not working, it might be because you haven't properly set up the column filtering. Here's how you can add filtering to your table columns:
<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>
)}
/>
<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>
)}
/>
This example shows how to add a filter dropdown to a column using the FilterDropdown component from refine Ant Design Table Filtering (https://refine.dev/docs/ui-integrations/ant-design/hooks/use-table/#filtering). 2. Local Filtering Instead of Server-Side: If the filtering is happening locally and not on the server, it's likely because the 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:
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
},
});
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
},
});
By setting 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). If you actually want to keep the filtering on the client side, you can leave the filters.mode as "off" and use Ant Design's built-in filtering capabilities:
<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}
/>
<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}
/>
This approach uses Ant Design's 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). Remember to adjust these examples according to your specific data structure and requirements. If you need more detailed assistance, please provide your current component code so I can give more specific advice. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai7mo ago
<@689846866837373077> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
rival-black
rival-black2mo ago
@kapa.ai
export 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>
export 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>
How can I pass the textfield value and menuitem when the search button is pressed?
kapa.ai
kapa.ai2mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I can help you implement search functionality in your refine application by passing both the TextField value and the selected MenuItem value when the search button is pressed. Based on your code, you're using Material UI components with refine's useForm hook. Here's how you can modify your code to achieve this:
export default function MembershipList() {
const [searchField, setSearchField] = useState("member_phone");

const {
handleSubmit,
reset,
register,
refineCore: { queryResult, onFinish },
} = useForm<HttpError>({
shouldUseNativeValidation: true,
refineCoreProps: {
resource: 'membership/subscribers',
action: 'create',
},
});

const onSubmitSearch = (data: any) => {
// Create filters based on the selected field and search value
const filters = [
{
field: searchField,
operator: "contains",
value: data.q,
},
];

// Pass the filters to refine's data provider
onFinish({ filters });
};

const resetForm = () => {
reset();
setSearchField("member_phone");
};
return (
<form onSubmit={handleSubmit(onSubmitSearch)}>
<Box mb={2}>
<Typography variant="h6">검색어</Typography>
<Grid container spacing={2}>
<Grid item xs={12} sm={2}>
<Select
value={searchField}
onChange={(e) => setSearchField(e.target.value)}
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>
</Box>
</form>
);
}
export default function MembershipList() {
const [searchField, setSearchField] = useState("member_phone");

const {
handleSubmit,
reset,
register,
refineCore: { queryResult, onFinish },
} = useForm<HttpError>({
shouldUseNativeValidation: true,
refineCoreProps: {
resource: 'membership/subscribers',
action: 'create',
},
});

const onSubmitSearch = (data: any) => {
// Create filters based on the selected field and search value
const filters = [
{
field: searchField,
operator: "contains",
value: data.q,
},
];

// Pass the filters to refine's data provider
onFinish({ filters });
};

const resetForm = () => {
reset();
setSearchField("member_phone");
};
return (
<form onSubmit={handleSubmit(onSubmitSearch)}>
<Box mb={2}>
<Typography variant="h6">검색어</Typography>
<Grid container spacing={2}>
<Grid item xs={12} sm={2}>
<Select
value={searchField}
onChange={(e) => setSearchField(e.target.value)}
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>
</Box>
</form>
);
}
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 function This implementation follows refine's pattern for search functionality as shown in the documentation for tables and search. The search will be performed when the user clicks the search button, passing both the selected field type and the search text to your data provider. Remember to adjust the filter operator ("contains" in this example) based on your specific requirements and data provider capabilities. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@1184365192482652173> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
rival-black
rival-black2mo ago
@kapa.ai Form is not "POST". "GET"
kapa.ai
kapa.ai2mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I understand you're having an issue with your form in refine where it's performing a "GET" request instead of a "POST" request. This is a common issue when working with forms in refine. Based on the knowledge sources, when you're using useForm 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. Here's how you can ensure your form performs a POST request:
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 {
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);
};
The key points to ensure your form performs a POST request: 1. Set action: 'create' in the refineCoreProps object when using useForm 2. For updating existing records, use action: 'edit' which will perform a PATCH/PUT request 3. Make sure you're using the onFinish function from the refineCore object returned by useForm to submit your form data If you're still experiencing issues, check if there are any interceptors or custom configurations in your data provider that might be changing the request method. If you need more specific help, please provide more details about your implementation, including your form component code and data provider configuration. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@1184365192482652173> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
rival-black
rival-black2mo ago
@kapa.ai How to request with GET instead of POST?
kapa.ai
kapa.ai2mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I understand you want to use a GET request instead of a POST request with refine's useForm hook. Let me explain how to achieve this. In refine, the 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. For search functionality with GET requests, you have a few options: 1. Use action: "list" with filters:
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 {
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 });
};
2. Use useTable hook instead: The useTable hook is better suited for search operations as it's designed to work with GET requests:
const {
tableProps,
searchFormProps,
filters,
setFilters,
} = useTable({
resource: 'membership/subscribers',
onSearch: (values) => {
return [
{
field: searchField,
operator: "contains",
value: values.q,
},
];
},
});
const {
tableProps,
searchFormProps,
filters,
setFilters,
} = useTable({
resource: 'membership/subscribers',
onSearch: (values) => {
return [
{
field: searchField,
operator: "contains",
value: values.q,
},
];
},
});
3. Modify the form submission to prevent default behavior: If you need to stick with your current form structure but want to use GET requests:
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 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);
});
};
The most appropriate approach for search functionality in refine is using the useTable hook as it's specifically designed for listing and filtering data with GET requests Frequently Asked Questions. Remember that when using forms for search, you'll want to ensure the form doesn't actually submit in the traditional way (which would trigger a page reload). Instead, you should handle the submission with JavaScript and use refine's data hooks to perform the GET request. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@1184365192482652173> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
rival-black
rival-black2mo ago
@kapa.ai How to fix?
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>
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>
kapa.ai
kapa.ai2mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I can see several issues in your code that need to be fixed to make the search functionality work properly with refine. Here's how to fix them: 1. First, you need to implement the form submission handler and connect your form fields to refine:
import { useTable, getDefaultFilter } from "@refinedev/core";
import { useForm, Controller } from "@refinedev/react-hook-form";
import { useState } from "react";

// Define your interface
interface IGroupFilterVariables {
q?: string;
field?: string;
}

export default function MembershipList() {
const [searchField, setSearchField] = useState("member_phone");

const { filters, setFilters } = useTable({
resource: 'membership/subscribers',
queryOptions: {
enabled: true, // Changed from !!dataGridProps?.rows which might be undefined initially
},
});

const { control, handleSubmit, reset } = useForm<IGroupFilterVariables, HttpError, IGroupFilterVariables>({
defaultValues: {
q: getDefaultFilter("q", filters, "contains") || "",
field: searchField
},
});

const onSubmit = (data: IGroupFilterVariables) => {
setFilters([
{
field: searchField,
operator: "contains",
value: data.q,
},
]);
};

const resetForm = () => {
reset();
setFilters([], "replace");
};
return (
<form method="GET" onSubmit={handleSubmit(onSubmit)}>
<Box mb={2}>
<Typography variant="h6">검색어</Typography>
<Grid container spacing={2}>
<Grid item xs={12} sm={2}>
<Select
value={searchField}
onChange={(e) => setSearchField(e.target.value as string)}
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}>
<Controller
control={control}
name="q"
render={({ field }) => (
<TextField
{...field}
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>
</form>
);
}
import { useTable, getDefaultFilter } from "@refinedev/core";
import { useForm, Controller } from "@refinedev/react-hook-form";
import { useState } from "react";

// Define your interface
interface IGroupFilterVariables {
q?: string;
field?: string;
}

export default function MembershipList() {
const [searchField, setSearchField] = useState("member_phone");

const { filters, setFilters } = useTable({
resource: 'membership/subscribers',
queryOptions: {
enabled: true, // Changed from !!dataGridProps?.rows which might be undefined initially
},
});

const { control, handleSubmit, reset } = useForm<IGroupFilterVariables, HttpError, IGroupFilterVariables>({
defaultValues: {
q: getDefaultFilter("q", filters, "contains") || "",
field: searchField
},
});

const onSubmit = (data: IGroupFilterVariables) => {
setFilters([
{
field: searchField,
operator: "contains",
value: data.q,
},
]);
};

const resetForm = () => {
reset();
setFilters([], "replace");
};
return (
<form method="GET" onSubmit={handleSubmit(onSubmit)}>
<Box mb={2}>
<Typography variant="h6">검색어</Typography>
<Grid container spacing={2}>
<Grid item xs={12} sm={2}>
<Select
value={searchField}
onChange={(e) => setSearchField(e.target.value as string)}
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}>
<Controller
control={control}
name="q"
render={({ field }) => (
<TextField
{...field}
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>
</form>
);
}
The key changes I made: 1. Added a handleSubmit function from useForm to handle form submission 2. Used Controller from @refinedev/react-hook-form to connect the TextField to the form state 3. Created an onSubmit function that uses setFilters to apply the search filter 4. Made the Select component controlled by adding a state variable and onChange handler 5. Implemented the resetForm function to clear both the form and filters 6. Fixed the getDefaultFilter usage to properly retrieve existing filter values This implementation follows refine's pattern for filtering as shown in the documentation for useTable filtering. The search will be performed when the user clicks the search button, passing both the selected field type and the search text to your data provider as a GET request. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@1184365192482652173> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
rival-black
rival-black2mo ago
kapa.ai
kapa.ai2mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I understand you're having an issue with the filter operator being transformed incorrectly in your refine application. The URL shows that you're using the "contains" operator for the "member_phone" field, but the server is receiving it as "member_phone_like" instead of the format you want. This is happening because refine's data providers typically transform filter operators to match the backend API's expected format. Based on the knowledge sources, the default behavior for many data providers is to map the "contains" operator to "_like" suffix:
const mapOperator = (operator) => {
switch (operator) {
case "contains":
return "_like";
case "eq":
default:
return "";
}
};
const mapOperator = (operator) => {
switch (operator) {
case "contains":
return "_like";
case "eq":
default:
return "";
}
};
This is shown in the data provider interface documentation. To fix this issue and get your desired format, you have a few options: 1. Create a custom data provider that maps the operators according to your needs 2. Use a different operator that maps to your desired format 3. Use initialFilter with undefined value to specify the operator without a value For the third option, there's a solution mentioned in a GitHub issue:
"I have find solution for my case: I can pass initialFilter with undefined value and useTable will be use operator from initialFilter" GitHub Issue #1199
Here's how you could implement this:
const { tableProps, filters, setFilters } = useTable({
resource: 'membership/subscribers',
filters: {
initial: [
{
field: "member_phone",
operator: "contains", // This will be used as the operator
value: undefined // Initially undefined
}
]
}
});
// Then when submitting your search form:
const onSubmit = (data) => {
setFilters([
{
field: "member_phone",
operator: "contains",
value: data.q
}
]);
};
const { tableProps, filters, setFilters } = useTable({
resource: 'membership/subscribers',
filters: {
initial: [
{
field: "member_phone",
operator: "contains", // This will be used as the operator
value: undefined // Initially undefined
}
]
}
});
// Then when submitting your search form:
const onSubmit = (data) => {
setFilters([
{
field: "member_phone",
operator: "contains",
value: data.q
}
]);
};
If you need more specific help with your data provider implementation, you might need to check which data provider you're using (Supabase, Hasura, etc.) as each has its own way of handling filter operators, and some have had issues with operators like "contains" as documented in the GitHub issues. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@1184365192482652173> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?