fix: custom table filterDropdown (#28850)

* fix: get origin keys from nested filters.

* fix: unexpected transformed filteredKyes with custom filterDropdown.

* fix: simplify code.
This commit is contained in:
Meowu 2021-01-15 22:51:03 +08:00 committed by GitHub
parent 6f69c89470
commit 0f0dc1577f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 110 additions and 28 deletions

View File

@ -5,6 +5,7 @@ import Table from '..';
import Input from '../../input';
import Tooltip from '../../tooltip';
import Button from '../../button';
import Select from '../../select';
import ConfigProvider from '../../config-provider';
// https://github.com/Semantic-Org/Semantic-UI-React/blob/72c45080e4f20b531fda2e3e430e384083d6766b/test/specs/modules/Dropdown/Dropdown-test.js#L73
@ -507,6 +508,7 @@ describe('Table.filter', () => {
});
it('three levels menu', () => {
const onChange = jest.fn();
const filters = [
{ text: 'Upper', value: 'Upper' },
{ text: 'Lower', value: 'Lower' },
@ -536,6 +538,7 @@ describe('Table.filter', () => {
filters,
},
],
onChange,
}),
);
jest.useFakeTimers();
@ -551,6 +554,10 @@ describe('Table.filter', () => {
dropdownWrapper = getDropdownWrapper(wrapper);
dropdownWrapper.find('MenuItem').last().simulate('click');
dropdownWrapper.find('.ant-table-filter-dropdown-btns .ant-btn-primary').simulate('click');
onChange.mock.calls.forEach(([, currentFilters]) => {
const [, val] = Object.entries(currentFilters)[0];
expect(val).toEqual(['Jack']);
});
wrapper.update();
expect(renderedNames(wrapper)).toEqual(['Jack']);
dropdownWrapper.find('MenuItem').last().simulate('click');
@ -906,6 +913,87 @@ describe('Table.filter', () => {
});
});
it('should work as expected with complex custom filterDropdown', () => {
const onChange = jest.fn();
const filterDropdown = ({ setSelectedKeys, selectedKeys, confirm }) => {
const handleChange = selectedValues => {
setSelectedKeys(selectedValues);
};
return (
<div>
<Select
mode="multiple"
allowClear
labelInValue
style={{ width: 200 }}
value={selectedKeys}
onChange={handleChange}
options={[
{
value: 1,
label: 'Not Identified',
},
{
value: 2,
label: 'Closed',
},
{
value: 3,
label: 'Communicated',
},
]}
/>
<button className="confirm-btn" type="submit" onClick={confirm}>
Confirm
</button>
</div>
);
};
const filteredValue = [
{
value: 2,
label: 'Closed',
},
];
const selectedValue = [
{
key: 2,
value: 2,
label: 'Closed',
},
{
key: 1,
value: 1,
label: 'Not Identified',
},
];
const wrapper = mount(
createTable({
onChange,
columns: [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
filterDropdown,
filteredValue,
},
],
}),
);
expect(wrapper.find('FilterDropdown').props().filterState.filteredKeys).toEqual(filteredValue);
wrapper.find('.ant-dropdown-trigger').first().simulate('click');
wrapper.find('.ant-select-selector').simulate('mousedown');
wrapper.find('.ant-select-item-option').first().simulate('click');
wrapper.find('.confirm-btn').first().simulate('click');
expect(onChange).toHaveBeenCalled();
onChange.mock.calls.forEach(([, currentFilters]) => {
const [, val] = Object.entries(currentFilters)[0];
expect(val).toEqual(selectedValue);
});
});
// https://github.com/ant-design/ant-design/issues/17089
it('not crash when dynamic change filter', () => {
const onChange = jest.fn();

View File

@ -34,9 +34,10 @@ function collectFilterStates<RecordType>(
} else if (column.filters || 'filterDropdown' in column || 'onFilter' in column) {
if ('filteredValue' in column) {
// Controlled
const filteredValues = Array.isArray(column.filteredValue)
? column.filteredValue.map(String)
: column.filteredValue;
let filteredValues = column.filteredValue;
if (!('filterDropdown' in column)) {
filteredValues = filteredValues?.map(String) ?? filteredValues;
}
filterStates.push({
column,
key: getColumnKey(column, columnPos),
@ -119,31 +120,6 @@ function injectFilter<RecordType>(
});
}
function generateFilterInfo<RecordType>(filterStates: FilterState<RecordType>[]) {
const currentFilters: Record<string, (Key | boolean)[] | null> = {};
filterStates.forEach(({ key, filteredKeys, column }) => {
const { filters, filterDropdown } = column;
if (filterDropdown) {
currentFilters[key] = filteredKeys || null;
} else {
const originKeys: ColumnFilterItem['value'][] = [];
if (Array.isArray(filteredKeys)) {
filters?.forEach((filter: ColumnFilterItem) => {
if (filteredKeys.includes(String(filter.value))) {
originKeys.push(filter.value);
}
});
currentFilters[key] = originKeys;
} else {
currentFilters[key] = null;
}
}
});
return currentFilters;
}
function flattenKeys(filters?: ColumnFilterItem[]) {
let keys: (string | number | boolean)[] = [];
(filters || []).forEach(({ value, children }) => {
@ -155,6 +131,24 @@ function flattenKeys(filters?: ColumnFilterItem[]) {
return keys;
}
function generateFilterInfo<RecordType>(filterStates: FilterState<RecordType>[]) {
const currentFilters: Record<string, (Key | boolean)[] | null> = {};
filterStates.forEach(({ key, filteredKeys, column }) => {
const { filters, filterDropdown } = column;
if (filterDropdown) {
currentFilters[key] = filteredKeys || null;
} else if (Array.isArray(filteredKeys)) {
const keys = flattenKeys(filters);
currentFilters[key] = keys.filter(originKey => filteredKeys.includes(String(originKey)));
} else {
currentFilters[key] = null;
}
});
return currentFilters;
}
export function getFilterData<RecordType>(
data: RecordType[],
filterStates: FilterState<RecordType>[],