Closed dfang closed 3 weeks ago
Hello @dfang, thanks for the issue!
we need to add defaultFilteredValue={getDefaultFilter("isActive", filters, "eq")}
to <Table.Column />
to populate column's default value.
more information is here: https://refine.dev/docs/ui-integrations/ant-design/hooks/use-table/#initial-filter-and-sorter
Do you want to work on this?
Also experinced this problem. Hopefully it can be added soon! By the way here's how I fixed it by a workaround:
const initialFilters: {[key: string]: string}[] = []
const currentUrl = new URL(location.href)
currentUrl.searchParams.forEach((value, key) => {
const matches = key.match(/filters\[(\d+)\]\[(.*?)\]/);
if (matches) {
const index = Number(matches[1]);
const field = matches[2];
// Ensure the filter object exists
if (!initialFilters[index]) {
initialFilters[index] = {};
}
// Assign the value to the appropriate field
initialFilters[index][field] = value;
}
})
<Table.Column
dataIndex="inspector"
key="inspector][id"
title="Inspector"
className="cursor-pointer"
render={(value) => value?.name}
defaultFilteredValue={initialFilters.filter(filter => filter.field === 'inspector][id').map(filter => filter.value)}
filterDropdown={(props) => (
<FilterDropdown {...props}>
<Select style={{ minWidth: 200 }} placeholder="Select inspector" {...inspectorsSelectProps} />
</FilterDropdown>
)}
/>
Hello @dzcpy,
Is this not working?
import { getDefaultFilter } from "@refinedev/core";
const { filters } = useTable();
// ...
defaultFilteredValue={getDefaultFilter("inspector][id", filters, "eq")}
// ...
Hello @dzcpy,
Is this not working?
import { getDefaultFilter } from "@refinedev/core"; const { filters } = useTable(); // ... defaultFilteredValue={getDefaultFilter("inspector][id", filters, "eq")} // ...
It doesn't work properly. It's just a hack. But this feature should really be integrated into Refine just like other fields (sorter and pagination from URL, if syncWithLocation is set to true)
Also when the field is a number or a boolean value, I need to convert the value to the respective type, otherwise filter select / checkbox will not find the default selected value.
I've changed it to something like this:
import { isNil } from 'lodash'
export const tableFiltersFromUrl = (url?: string) => {
if (!url) {
url = window.location.href
}
return Array.from(new URL(url).searchParams.entries()).reduce((acc, [key, value]) => {
if (key.startsWith('filters[')) {
const matches = key.match(/filters\[(?<index>\d+)\]\[(?<item>.*?)\]/)
if (matches?.groups?.index && matches?.groups?.item) {
const index = Number(matches.groups.index)
const field = matches.groups.item
// Ensure the filter object exists
if (!acc[index]) {
acc[index] = {}
}
// Assign the value to the appropriate field
acc[index][field] = value
}
}
return acc
}, [] as { [key: string]: string }[])
.filter(filter => filter.field && filter.operator && !isNil(filter.value)) as { field: string, operator: string, value: string }[]
}
export const tableFiltersGetDefaultValue = (filters: ReturnType<typeof tableFiltersFromUrl>, field: string, type: 'string' | 'number' | 'boolean' = 'string') =>
filters.filter(filter => filter.field === field).map(filter => type === 'boolean' ? /^true$/i.test(filter.value) : type === 'number' ? Number(filter.value) : filter.value)
const initialFilters = useMemo(() => tableFiltersFromUrl(), [])
<Table.Column
dataIndex="name"
key="name"
title="Name"
defaultFilteredValue={tableFiltersGetDefaultValue(initialFilters, 'name')}
filterDropdown={(props) => (
<FilterDropdown {...props}>
<Input style={{ minWidth: 200 }} placeholder="Please input name" />
</FilterDropdown>
)}
className="cursor-pointer"
/>
<Table.Column
dataIndex="inspector"
key="inspector][id"
title="Inspector"
className="cursor-pointer"
render={(value) => value?.name}
defaultFilteredValue={tableFiltersGetDefaultValue(initialFilters, 'inspector][id', 'number')}
filterDropdown={(props) => (
<FilterDropdown {...props}>
<Select style={{ minWidth: 200 }} placeholder="Please select inspector" {...inspectorsSelectProps} />
</FilterDropdown>
)}
/>
<Table.Column
dataIndex="finished"
key="finished"
title="Finished?"
render={(value) => (value ? locationFinishedOptions.true : locationFinishedOptions.false)}
defaultFilteredValue={tableFiltersGetDefaultValue(initialFilters, 'finished', 'boolean')}
filterDropdown={(props) => (
<FilterDropdown {...props}>
<Select
style={{ minWidth: 200 }}
placeholder="Choose if it's finished"
filterOption={false}
options={Object.entries(locationFinishedOptions).map(([value, label]) => ({ value, label }))}
/>
</FilterDropdown>
)}
className="cursor-pointer"
/>
@dzcpy Thanks for the detailed explanation, you are right there is room for improvement. We'll think about it.
Is your feature request related to a problem? Please describe.
this is a list of customers filtered with idle status,
https://example.admin.refine.dev/customers?pageSize=10¤t=9&sorters[0][field]=isActive&sorters[0][order]=asc&filters[0][field]=fullName&filters[0][operator]=contains
when I refresh the page, the list is not filtered with idle status.
Describe alternatives you've considered
No response
Additional context
when you filter then click pagination number, it's ok. but refresh and click pagination number, it's not filtered
Describe the thing to improve
keep the filter after refreshing the page (restore filters from url)