absent-sapphire•2mo ago
Select in ant dropdown filter
I'm building a custom table column dropdown filter using ant design components that uses a <Select> component as the filter input, and I'm having trouble with it rendering correctly. Initially, it displays all the options and, when an option is selected, it filters correctly, but subsequently, when I open the <DropdownFilter> again, the select displays the internal value of the selected option, not the label. Here's the relevant code:
<FilterDropdown {...props}>
<Select placeholder={filterPrompt} options={columnProps.filterProps?.enumerations}
allowClear value={props.selectedKeys?.[0] || undefined}
onChange={(val) => {
props.setSelectedKeys(val ? [val] : []);
props.confirm();
}} />
</FilterDropdown>
How can I get the select to always render the label of the selected option?
17 Replies
Hi @Hypnotic Meat. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
The issue you're experiencing—where the Ant Design
Ant Design's Table filter system always serializes filter values as strings (especially when syncing with the URL), but your
Add the
<Select> in a <FilterDropdown> shows the internal value (e.g., an ID) instead of the label after filtering or re-opening—is a known challenge when the value types (string vs. number) or mapping between value and label are not handled correctly. This is especially common when the filter value comes from the URL or is synced with location, as Ant Design always normalizes selected keys to strings, but your options may use numbers or other types as values.
Solution: Use the mapValue prop in <FilterDropdown> to normalize value types
Refine provides a mapValue prop on <FilterDropdown> to help you map the selected keys (which are always strings from Ant Design) back to the correct type (e.g., number) expected by your options. This ensures that the <Select> component can correctly match the value to its label and display the label instead of the raw value.
Here's how you can update your code:
- The mapValue function converts the string keys back to numbers (or whatever type your option values are).
- This ensures that the <Select> component can find the correct label for the selected value and display it properly.
Reference Example from Refine Docs:
See the official documentation for more details and examples.
Why this happens:Ant Design's Table filter system always serializes filter values as strings (especially when syncing with the URL), but your
<Select> options may use numbers or other types. Without mapping, the <Select> can't match the value to the label, so it just displays the raw value.
Summary:Add the
mapValue prop to your <FilterDropdown> and ensure it converts the selected keys to the correct type for your <Select> options. This will ensure the label is always displayed correctly, even after filtering or page reloads.
FilterDropdown mapValue property documentation
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@224018850419572736> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
absent-sapphireOP•2mo ago
@kapa.ai changing it to onSelect fixed my issue, thanks. Now I have a different problem with a <DatePicker> filter. Consider the following code:
<FilterDropdown {...props}>
<DatePicker placeholder={filterPrompt} />
</FilterDropdown>
When I initially filter, I can see that the url parameter is correctly passing the selected date. However, when I open the filter dropdown subsequently, I get the error: "date.isValid is not a function". What am I doing wrong?
Let me check the knowledge base for you again. One moment! :books:
----------------------
The error
You need to use the
This pattern is described in the Refine documentation for handling date filters with
See the official documentation for details and examples. Summary:
Always use
"date.isValid is not a function" when re-opening a <DatePicker> filter in a <FilterDropdown> is a known issue that occurs because, when the filter value is restored from the URL (with syncWithLocation enabled), it is a string rather than a Dayjs object. Ant Design's <DatePicker> expects a Dayjs object as its value, so passing a string causes this error.
How to fix:You need to use the
mapValue prop on <FilterDropdown> to convert the string value (from the URL or filter state) back into a Dayjs object before passing it to <DatePicker>. Here’s how you can do it:
This approach ensures that:
- When the filter value is restored from the URL (as a string), it is converted to a Dayjs object for the <DatePicker>.
- When the value changes, it is stored as a string (ISO format), which is compatible with URL sync and Refine’s filtering.
Reference:This pattern is described in the Refine documentation for handling date filters with
<FilterDropdown>, especially when using syncWithLocation or restoring filter values from the URL. The same principle is used for <DatePicker.RangePicker> with the rangePickerFilterMapper utility, but for a single date, you can use a similar mapping function as shown above.See the official documentation for details and examples. Summary:
Always use
mapValue to convert string values from the filter state or URL into Dayjs objects before passing them to <DatePicker>. This will prevent the "date.isValid is not a function" error and ensure your filter works correctly after page reloads or when restoring from the URL.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@224018850419572736> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
absent-sapphireOP•2mo ago
@kapa.ai when I add the mapValue function, it errors out that selectedKeys.map is not a function. When I log it to console, I can see that selectedKeys is a dayjs object
Let me check the knowledge base for you again. One moment! :books:
----------------------
You're encountering this error because, depending on the event and the state of the filter,
This pattern is consistent with the guidance in the Refine documentation, which notes that filter values restored from the URL may not always be in the expected format and may require normalization before being passed to Ant Design components. The documentation also highlights the importance of type normalization when using the
selectedKeys can be either an array or a single value (such as a Dayjs object or a string). The .map function only works on arrays, so if selectedKeys is not an array, calling .map will throw an error.
How to handle this:
You should check the type of selectedKeys before calling .map. If it's not an array, wrap it in an array or handle it accordingly. Here’s an example pattern:
This approach ensures that .map is always called on an array, preventing the error you saw.
Reference:This pattern is consistent with the guidance in the Refine documentation, which notes that filter values restored from the URL may not always be in the expected format and may require normalization before being passed to Ant Design components. The documentation also highlights the importance of type normalization when using the
mapValue prop, especially for date and select filters, to avoid type mismatches and runtime errors FilterDropdown mapValue property documentation.
If you continue to see issues, double-check the value of selectedKeys in both "value" and "onChange" events, as their structure may differ depending on how the filter is being restored or updated.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@224018850419572736> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
absent-sapphireOP•2mo ago
@kapa.ai ok, now when I filter, a filter value for each property on the dayjs object is being added to the url. I only want the serialized date string to be passed to the server backend. How can I modify it to do that?
Let me check the knowledge base for you again. One moment! :books:
----------------------
The issue you're seeing—where each property of the Dayjs object is being added to the URL—happens when the filter value is not properly serialized to a string before being stored or synced with the URL. This typically occurs if the
You need to ensure that, in your
-
This approach is directly aligned with the official Refine documentation, which explains how to use
Update your
mapValue function does not convert the Dayjs object to an ISO string on the "onChange" event.
How to fix:You need to ensure that, in your
mapValue function, you convert the Dayjs object to a string (e.g., using .toISOString()) when the event is "onChange". This way, only the serialized date string will be stored in the filter state and passed to the backend.
Here’s how you can modify your mapValue function:
Why this works:-
"value" event: Ensures the DatePicker always receives a Dayjs object.
- "onChange" event: Ensures only the ISO string is stored in the filter state and URL, preventing all Dayjs properties from being serialized.
Reference:This approach is directly aligned with the official Refine documentation, which explains how to use
mapValue to convert between Dayjs objects and ISO strings for date filters, especially when using URL sync or restoring filter values from the URL. See the FilterDropdown documentation for more details and examples.
---
Summary:Update your
mapValue function to serialize Dayjs objects to ISO strings on "onChange". This will ensure only the date string is passed to your backend and stored in the URL, resolving the issue.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@224018850419572736> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
absent-sapphireOP•2mo ago
@kapa.ai ok, that's working. Now, how can I add an additional control to the <FilterDropdown> that allows users to change the type of filtering for the date picker to things like 'before' or 'after'?
Let me check the knowledge base for you again. One moment! :books:
----------------------
The knowledge sources indicate that, by default, Refine’s
There is no built-in way in Refine’s
<FilterDropdown> and Ant Design’s table filtering use the eq operator for simple values and in for arrays. To use a different operator (like gte for "after" or lte for "before") with a date picker, you need to set the initial filter with the desired operator using the initial filter option in useTable. This approach is confirmed in Github Issue #1199, where setting an initialFilter with an undefined value allows you to specify the operator.
However, dynamically changing the operator from within the filter dropdown UI (e.g., letting the user pick "before", "after", or "on" from a select) is not natively supported out-of-the-box in Refine or Ant Design, according to the current documentation and issues. There are feature requests for this (#1691, #1373), but as of now, you would need to implement a custom solution.
What you can do:
- You can add a <Select> inside your <FilterDropdown> to let the user choose the operator.
- In your onChange handler, you would need to update both the value and the operator in the filter state.
- However, Refine’s current filter handling does not provide a direct way to change the operator from the dropdown UI; it expects the operator to be set in the filter definition or via initialFilter.
Summary:There is no built-in way in Refine’s
<FilterDropdown> to let users dynamically change the filter operator (e.g., "before", "after", "on") for a date picker from the dropdown UI. You can set the operator via initialFilter in useTable, but for a fully dynamic UI, you would need to implement custom filter logic and state management outside of the standard Refine hooks.
If you need a reference for setting the operator via initialFilter, see this comment:
I can passIf you want to explore a custom solution, you may need to manage the filter state yourself and update both the value and operator based on user input, but this is not covered in the official documentation or examples. --- If you need a code example or further guidance on a custom implementation, let me know! ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------initialFilterwith undefined value anduseTablewill use operator frominitialFilter.
<@224018850419572736> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
absent-sapphireOP•2mo ago
@kapa.ai yeah, can you provide a custom code sample for a simple way of setting both the filter value and filter operator?
Let me check the knowledge base for you again. One moment! :books:
----------------------
Certainly! Based on the knowledge sources, there is no built-in way in Refine’s
Advanced Table Search Example
Blog Example: Customizable Issue Tracker. Note:
If you want to use this approach in a column filter dropdown, you would need to manage the filter state yourself and update both the value and operator, but this is not directly supported by Refine’s built-in
<FilterDropdown> to dynamically change the filter operator from the dropdown UI. However, you can implement a custom filter UI outside of the standard column filter, using a form and the onSearch prop of useTable to set both the value and the operator. This approach is demonstrated in the official documentation and blog examples for advanced table search and filtering.
Here’s a simplified example using a form with a <Select> for the operator and a <DatePicker> for the value, then passing both to onSearch in useTable:
This pattern is consistent with the advanced search and filter examples in the Refine documentation, where you use a custom form to control both the filter value and operator, and return a CrudFilters array in onSearch to update the table data accordinglyAdvanced Table Search Example
Blog Example: Customizable Issue Tracker. Note:
If you want to use this approach in a column filter dropdown, you would need to manage the filter state yourself and update both the value and operator, but this is not directly supported by Refine’s built-in
<FilterDropdown> as of now.
If you need a column filter dropdown version, let me know!
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@224018850419572736> Kapa.ai is still learning and improving, please let me know how I did by reacting below.