-
-
Notifications
You must be signed in to change notification settings - Fork 141
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add displayInInput option to allow externally controlled search #548
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
--- | ||
title: external search | ||
nav: | ||
title: Demo | ||
path: /demo | ||
--- | ||
|
||
<code src="../../examples/external-search.tsx"></code> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import React, { useState } from 'react'; | ||
import '../assets/index.less'; | ||
import Cascader from '../src'; | ||
|
||
const addressOptions = [ | ||
{ | ||
label: '福建', | ||
value: 'fj', | ||
children: [ | ||
{ | ||
label: '福州', | ||
value: 'fuzhou', | ||
children: [ | ||
{ | ||
label: '马尾-mw', | ||
value: 'mawei', | ||
}, | ||
], | ||
}, | ||
{ | ||
label: '泉州-qz', | ||
value: 'quanzhou', | ||
}, | ||
], | ||
}, | ||
{ | ||
label: '浙江', | ||
value: 'zj', | ||
children: [ | ||
{ | ||
label: '杭州', | ||
value: 'hangzhou', | ||
children: [ | ||
{ | ||
label: '余杭', | ||
value: 'yuhang', | ||
}, | ||
{ | ||
label: '福州', | ||
value: 'fuzhou', | ||
children: [ | ||
{ | ||
label: '马尾', | ||
value: 'mawei', | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
{ | ||
label: '北京', | ||
value: 'bj', | ||
children: [ | ||
{ | ||
label: '朝阳区', | ||
value: 'chaoyang', | ||
}, | ||
{ | ||
label: '海淀区', | ||
value: 'haidian', | ||
}, | ||
], | ||
}, | ||
]; | ||
|
||
const Demo = () => { | ||
const [searchValue, setSearchValue] = useState(''); | ||
return ( | ||
<> | ||
<Cascader | ||
options={addressOptions} | ||
showSearch={{ displayInInput: false }} | ||
searchValue={searchValue} | ||
style={{ width: 300 }} | ||
dropdownRender={menu => { | ||
return ( | ||
<div> | ||
<input | ||
value={searchValue} | ||
onChange={e => setSearchValue(e.target.value)} | ||
placeholder="External Search" | ||
/> | ||
Comment on lines
+80
to
+84
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 改进输入框的可访问性和用户体验 搜索输入框缺少一些重要的可访问性和用户体验特性:
建议修改如下: <input
value={searchValue}
onChange={e => setSearchValue(e.target.value)}
placeholder="External Search"
+ type="search"
+ aria-label="外部搜索输入框"
+ className="external-search-input"
/> 另外,建议在输入框旁添加搜索图标: import { SearchOutlined } from '@ant-design/icons';
// 在输入框前添加图标
<span className="search-icon">
<SearchOutlined />
</span> |
||
{menu} | ||
</div> | ||
); | ||
}} | ||
animation="slide-up" | ||
notFoundContent="Empty Content!" | ||
/> | ||
</> | ||
); | ||
}; | ||
|
||
export default Demo; |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,7 +1,7 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { fireEvent, render } from '@testing-library/react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import KeyCode from 'rc-util/lib/KeyCode'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { resetWarned } from 'rc-util/lib/warning'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import React from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import React, { useState } from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import Cascader from '../src'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { optionsForActiveMenuItems } from './demoOptions'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import type { ReactWrapper } from './enzyme'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -73,6 +73,49 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
expect(onChange).toHaveBeenCalledWith(['bamboo', 'little', 'fish'], expect.anything()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
it('externally controlled search',() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const onSearch = jest.fn(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const onChange = jest.fn(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
function doExternalSearch(wrapper: ReactWrapper, search: string) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
wrapper.find('input[data-test="external-search"]').simulate('change', { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
target: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
value: search, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const ExternallyControlledSearch = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const [searchValue,setSearchValue] = useState('') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<input data-test="external-search" value={searchValue} onChange={e => setSearchValue(e.target.value)} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Cascader options={options} searchValue={searchValue} onChange={onChange} onSearch={onSearch} open showSearch={{displayInInput:false}} />, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+89
to
+97
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 需要修复测试组件中的语法和类型问题 ExternallyControlledSearch 组件存在以下问题:
-const ExternallyControlledSearch = () => {
- const [searchValue,setSearchValue] = useState('')
+interface ExternallyControlledSearchProps {}
+
+const ExternallyControlledSearch: React.FC<ExternallyControlledSearchProps> = () => {
+ const [searchValue, setSearchValue] = useState<string>('')
return (
<>
<input data-test="external-search" value={searchValue} onChange={e => setSearchValue(e.target.value)} />
- <Cascader options={options} searchValue={searchValue} onChange={onChange} onSearch={onSearch} open showSearch={{displayInInput:false}} />,
+ <Cascader
+ options={options}
+ searchValue={searchValue}
+ onChange={onChange}
+ onSearch={onSearch}
+ open
+ showSearch={{ displayInInput: false }}
+ />
</>
);
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const wrapper = mount(<ExternallyControlledSearch/>) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Leaf | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
doExternalSearch(wrapper, 'toy'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let itemList = wrapper.find('div.rc-cascader-menu-item-content'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
expect(itemList).toHaveLength(2); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
expect(itemList.at(0).text()).toEqual('Label Bamboo / Label Little / Toy Fish'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
expect(itemList.at(1).text()).toEqual('Label Bamboo / Label Little / Toy Cards'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Parent | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
doExternalSearch(wrapper, 'Label Little'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
itemList = wrapper.find('div.rc-cascader-menu-item-content'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
expect(itemList).toHaveLength(2); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
expect(itemList.at(0).text()).toEqual('Label Bamboo / Label Little / Toy Fish'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
expect(itemList.at(1).text()).toEqual('Label Bamboo / Label Little / Toy Cards'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
wrapper.clickOption(0, 0); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
expect(onChange).toHaveBeenCalledWith(['bamboo', 'little', 'fish'], expect.anything()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Check notice Code scanning / CodeQL Semicolon insertion Note test
Avoid automated semicolon insertion (94% of all statements in
the enclosing function Error loading related location Loading |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
it('changeOnSelect', () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const onChange = jest.fn(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const wrapper = mount( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
建议添加输入验证和错误处理
当前实现缺少输入验证和错误处理机制:
建议添加以下功能: