Skip to content

Commit 251a032

Browse files
headwindzn0ruShzombieJ
authored
feat: add sorting functionality (#558)
* feat: add sorting functionality * feat: replace sort and sortOrder to filterSort and sorting only works for search filter * fix: test case and demo * refactor: immutable array sort * fix: typescript error * chore: Show scrollbar when open (#557) * chore: Show scrollbar when open * fix logic * 11.4.2 * chore: Use github action * chore: RM circle ci * docs: Update badge Co-authored-by: n0ruSh <[email protected]> Co-authored-by: 二货机器人 <[email protected]>
1 parent 0fa287b commit 251a032

File tree

4 files changed

+70
-2
lines changed

4 files changed

+70
-2
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ export default () => (
100100
| disabled | whether disabled select | bool | false |
101101
| filterOption | whether filter options by input value. default filter by option's optionFilterProp prop's value | bool | true/Function(inputValue:string, option:Option) |
102102
| optionFilterProp | which prop value of option will be used for filter if filterOption is true | String | 'value' |
103+
| filterSort | Sort function for search options sorting, see [Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)'s compareFunction. | Function(optionA:Option, optionB: Option) | - |
103104
| optionLabelProp | render option value or option children as content of select | String: 'value'/'children' | 'value' |
104105
| defaultValue | initial selected option(s) | String/Array<String> | - |
105106
| value | current selected option(s) | String/Array<String>/{key:String, label:React.Node}/Array<{key, label}> | - |

examples/filterSort.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import React from 'react';
2+
import Select from '../src';
3+
import '../assets/index.less';
4+
5+
const incidencesStateResource = [
6+
{ value: 4, label: 'Not Identified' },
7+
{ value: 3, label: 'Closed' },
8+
{ value: 2, label: 'Communicated' },
9+
{ value: 6, label: 'Identified' },
10+
{ value: 1, label: 'Resolved' },
11+
{ value: 5, label: 'Cancelled' },
12+
];
13+
14+
const sorterByLabel = (optionA, optionB) => optionA.label.localeCompare(optionB.label);
15+
16+
const Test = () => (
17+
<div>
18+
<h3> with filter sort </h3>
19+
<Select
20+
showSearch
21+
style={{ width: 500 }}
22+
filterSort={sorterByLabel}
23+
optionFilterProp="label"
24+
options={incidencesStateResource}
25+
></Select>
26+
<h3> without filter sort </h3>
27+
<Select
28+
showSearch
29+
style={{ width: 500 }}
30+
optionFilterProp="label"
31+
options={incidencesStateResource}
32+
/>
33+
</div>
34+
);
35+
36+
export default Test;

src/generate.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export interface SelectProps<OptionsType extends object[], ValueType> extends Re
8585
* It's by design.
8686
*/
8787
filterOption?: boolean | FilterFunc<OptionsType[number]>;
88+
filterSort?: (optionA: OptionsType[number], optionB: OptionsType[number]) => number;
8889
showSearch?: boolean;
8990
autoClearSearchValue?: boolean;
9091
onSearch?: (value: string) => void;
@@ -187,7 +188,7 @@ export interface GenerateConfig<OptionsType extends object[]> {
187188
/** Convert single raw value into { label, value } format. Will be called by each value */
188189
getLabeledValue: GetLabeledValue<FlattenOptionsType<OptionsType>>;
189190
filterOptions: FilterOptions<OptionsType>;
190-
findValueOption: // Need still support legacy ts api
191+
findValueOption:// Need still support legacy ts api
191192
| ((values: RawValueType[], options: FlattenOptionsType<OptionsType>) => OptionsType)
192193
// New API add prevValueOptions support
193194
| ((
@@ -258,6 +259,7 @@ export default function generateSelector<
258259
inputValue,
259260
searchValue,
260261
filterOption,
262+
filterSort,
261263
optionFilterProp = 'value',
262264
autoClearSearchValue = true,
263265
onSearch,
@@ -443,9 +445,12 @@ export default function generateSelector<
443445
key: '__RC_SELECT_TAG_PLACEHOLDER__',
444446
});
445447
}
448+
if (filterSort && Array.isArray(filteredOptions)) {
449+
return ([...filteredOptions] as OptionsType).sort(filterSort);
450+
}
446451

447452
return filteredOptions;
448-
}, [mergedOptions, mergedSearchValue, mode, mergedShowSearch]);
453+
}, [mergedOptions, mergedSearchValue, mode, mergedShowSearch, filterSort]);
449454

450455
const displayFlattenOptions: FlattenOptionsType<OptionsType> = useMemo(
451456
() => flattenOptions(displayOptions, props),

tests/Select.test.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1624,4 +1624,30 @@ describe('Select.Basic', () => {
16241624
.first()
16251625
.simulate('mouseenter');
16261626
});
1627+
1628+
it('filterSort should work', () => {
1629+
const wrapper = mount(
1630+
<Select
1631+
showSearch
1632+
filterSort={(optionA, optionB) =>
1633+
(optionA.label as string).localeCompare(optionB.label as string)
1634+
}
1635+
optionFilterProp="label"
1636+
options={[
1637+
{ value: 4, label: 'Not Identified' },
1638+
{ value: 3, label: 'Closed' },
1639+
{ value: 2, label: 'Communicated' },
1640+
{ value: 5, label: 'Cancelled' },
1641+
]}
1642+
/>,
1643+
);
1644+
1645+
wrapper.find('input').simulate('change', { target: { value: 'i' } });
1646+
expect(
1647+
wrapper
1648+
.find('.rc-select-item-option-content')
1649+
.first()
1650+
.text(),
1651+
).toBe('Communicated');
1652+
});
16271653
});

0 commit comments

Comments
 (0)