Skip to content

Commit 3ac4503

Browse files
authored
fix single backfill logic (#515)
1 parent 51df020 commit 3ac4503

File tree

2 files changed

+83
-24
lines changed

2 files changed

+83
-24
lines changed

src/Selector/SingleSelector.tsx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,23 @@ const SingleSelector: React.FC<SelectorProps> = props => {
3737
onInputCompositionEnd,
3838
} = props;
3939

40+
const [inputChanged, setInputChanged] = React.useState(false);
41+
4042
const combobox = mode === 'combobox';
4143
const inputEditable = combobox || (showSearch && open);
4244
const item = values[0];
4345

44-
const getDisplayValue = (value: React.ReactText): string => (value === null ? '' : String(value));
45-
let inputValue: string = searchValue;
46-
if (combobox) {
47-
inputValue = item ? getDisplayValue(item.value) : activeValue || searchValue;
46+
let inputValue: string = searchValue || '';
47+
if (combobox && activeValue && !inputChanged) {
48+
inputValue = activeValue;
4849
}
4950

51+
React.useEffect(() => {
52+
if (combobox) {
53+
setInputChanged(false);
54+
}
55+
}, [combobox, activeValue]);
56+
5057
// Not show text when closed expect combobox mode
5158
const hasTextInput = mode !== 'combobox' && !open ? false : !!inputValue;
5259

@@ -67,7 +74,10 @@ const SingleSelector: React.FC<SelectorProps> = props => {
6774
value={inputValue}
6875
onKeyDown={onInputKeyDown}
6976
onMouseDown={onInputMouseDown}
70-
onChange={onInputChange}
77+
onChange={e => {
78+
setInputChanged(true);
79+
onInputChange(e as any);
80+
}}
7181
onPaste={onInputPaste}
7282
onCompositionStart={onInputCompositionStart}
7383
onCompositionEnd={onInputCompositionEnd}

tests/Combobox.test.tsx

Lines changed: 68 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -213,25 +213,74 @@ describe('Select.Combobox', () => {
213213
});
214214
});
215215

216-
it('backfill', () => {
217-
const handleChange = jest.fn();
218-
const handleSelect = jest.fn();
219-
const wrapper = mount(
220-
<Select mode="combobox" backfill open onChange={handleChange} onSelect={handleSelect}>
221-
<Option value="One">One</Option>
222-
<Option value="Two">Two</Option>
223-
</Select>,
224-
);
225-
const input = wrapper.find('input');
226-
input.simulate('keyDown', { which: KeyCode.DOWN });
227-
expect(wrapper.find('input').props().value).toEqual('One');
228-
expect(handleChange).not.toHaveBeenCalled();
229-
expect(handleSelect).not.toHaveBeenCalled();
230-
231-
input.simulate('keyDown', { which: KeyCode.ENTER });
232-
expect(wrapper.find('input').props().value).toEqual('One');
233-
expect(handleChange).toHaveBeenCalledWith('One', expect.objectContaining({ value: 'One' }));
234-
expect(handleSelect).toHaveBeenCalledWith('One', expect.objectContaining({ value: 'One' }));
216+
describe('backfill', () => {
217+
it('basic', () => {
218+
const handleChange = jest.fn();
219+
const handleSelect = jest.fn();
220+
const wrapper = mount(
221+
<Select mode="combobox" backfill open onChange={handleChange} onSelect={handleSelect}>
222+
<Option value="One">One</Option>
223+
<Option value="Two">Two</Option>
224+
</Select>,
225+
);
226+
const input = wrapper.find('input');
227+
input.simulate('keyDown', { which: KeyCode.DOWN });
228+
expect(wrapper.find('input').props().value).toEqual('One');
229+
expect(handleChange).not.toHaveBeenCalled();
230+
expect(handleSelect).not.toHaveBeenCalled();
231+
232+
input.simulate('keyDown', { which: KeyCode.ENTER });
233+
expect(wrapper.find('input').props().value).toEqual('One');
234+
expect(handleChange).toHaveBeenCalledWith('One', expect.objectContaining({ value: 'One' }));
235+
expect(handleSelect).toHaveBeenCalledWith('One', expect.objectContaining({ value: 'One' }));
236+
});
237+
238+
// https://github.com/ant-design/ant-design/issues/25345
239+
it('dynamic options', () => {
240+
const onChange = jest.fn();
241+
242+
const Test = () => {
243+
const [options, setOptions] = React.useState([]);
244+
const onSearch = (value: string) => {
245+
let res = [];
246+
247+
if (!value || value.indexOf('@') >= 0) {
248+
res = [];
249+
} else {
250+
const email = `${value}@gmail.com`;
251+
res = [{ value: email, label: email }];
252+
}
253+
setOptions(res);
254+
};
255+
return (
256+
<Select
257+
backfill
258+
mode="combobox"
259+
onChange={onChange}
260+
onSearch={onSearch}
261+
options={options}
262+
/>
263+
);
264+
};
265+
266+
const wrapper = mount(<Test />);
267+
268+
function input() {
269+
return wrapper.find('input');
270+
}
271+
272+
input().simulate('change', { target: { value: 'light' } });
273+
expectOpen(wrapper);
274+
expect(onChange).toHaveBeenCalledWith('light', expect.anything());
275+
onChange.mockReset();
276+
277+
input().simulate('keyDown', { which: KeyCode.DOWN });
278+
expect(input().props().value).toEqual('[email protected]');
279+
expect(onChange).not.toHaveBeenCalled();
280+
281+
input().simulate('keyDown', { which: KeyCode.ENTER });
282+
expect(onChange).toHaveBeenCalledWith('[email protected]', expect.anything());
283+
});
235284
});
236285

237286
it("should hide clear icon when value is ''", () => {

0 commit comments

Comments
 (0)