Browse Source

feat: add showCheckedStrategy api for cascader (#34568)

* feat: add showCheckedStrategy api for cascader

* feat: update doc

* feat: add demo and update doc

* feat: update demo
pull/34738/head
黑雨 3 years ago
committed by GitHub
parent
commit
215d2ad883
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 308
      components/cascader/__tests__/__snapshots__/index.test.js.snap
  2. 131
      components/cascader/__tests__/index.test.js
  3. 90
      components/cascader/demo/showCheckedStrategy.md
  4. 3
      components/cascader/index.en-US.md
  5. 8
      components/cascader/index.tsx
  6. 1
      components/cascader/index.zh-CN.md

308
components/cascader/__tests__/__snapshots__/index.test.js.snap

@ -864,6 +864,314 @@ exports[`Cascader can be selected in RTL direction 3`] = `
</div>
`;
exports[`Cascader legacy props should support showCheckedStrategy child 1`] = `
<div
class="ant-select ant-cascader ant-select-multiple ant-select-allow-clear ant-select-open"
>
<div
class="ant-select-selector"
>
<div
class="ant-select-selection-overflow"
>
<div
class="ant-select-selection-overflow-item ant-select-selection-overflow-item-suffix"
style="opacity: 1;"
>
<div
class="ant-select-selection-search"
style="width: 0px;"
>
<input
aria-autocomplete="list"
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
aria-haspopup="listbox"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="ant-select-selection-search-input"
id="rc_select_TEST_OR_SSR"
readonly=""
role="combobox"
style="opacity: 0;"
type="search"
unselectable="on"
value=""
/>
<span
aria-hidden="true"
class="ant-select-selection-search-mirror"
>
 
</span>
</div>
</div>
</div>
<span
class="ant-select-selection-placeholder"
/>
</div>
<div>
<div
class="ant-select-dropdown ant-cascader-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up"
style="opacity: 0; pointer-events: none; min-width: auto;"
>
<div>
<div
class="ant-cascader-menus"
>
<ul
class="ant-cascader-menu"
role="menu"
>
<li
aria-checked="false"
class="ant-cascader-menu-item ant-cascader-menu-item-expand"
data-path-key="zhejiang"
role="menuitemcheckbox"
title="Zhejiang"
>
<span
class="ant-cascader-checkbox"
>
<span
class="ant-cascader-checkbox-inner"
/>
</span>
<div
class="ant-cascader-menu-item-content"
>
Zhejiang
</div>
<div
class="ant-cascader-menu-item-expand-icon"
>
<span
aria-label="right"
class="anticon anticon-right"
role="img"
>
<svg
aria-hidden="true"
data-icon="right"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
/>
</svg>
</span>
</div>
</li>
<li
aria-checked="false"
class="ant-cascader-menu-item ant-cascader-menu-item-expand"
data-path-key="jiangsu"
role="menuitemcheckbox"
title="Jiangsu"
>
<span
class="ant-cascader-checkbox"
>
<span
class="ant-cascader-checkbox-inner"
/>
</span>
<div
class="ant-cascader-menu-item-content"
>
Jiangsu
</div>
<div
class="ant-cascader-menu-item-expand-icon"
>
<span
aria-label="right"
class="anticon anticon-right"
role="img"
>
<svg
aria-hidden="true"
data-icon="right"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
/>
</svg>
</span>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
`;
exports[`Cascader legacy props should support showCheckedStrategy parent 1`] = `
<div
class="ant-select ant-cascader ant-select-multiple ant-select-allow-clear ant-select-open"
>
<div
class="ant-select-selector"
>
<div
class="ant-select-selection-overflow"
>
<div
class="ant-select-selection-overflow-item ant-select-selection-overflow-item-suffix"
style="opacity: 1;"
>
<div
class="ant-select-selection-search"
style="width: 0px;"
>
<input
aria-autocomplete="list"
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
aria-haspopup="listbox"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="ant-select-selection-search-input"
id="rc_select_TEST_OR_SSR"
readonly=""
role="combobox"
style="opacity: 0;"
type="search"
unselectable="on"
value=""
/>
<span
aria-hidden="true"
class="ant-select-selection-search-mirror"
>
 
</span>
</div>
</div>
</div>
<span
class="ant-select-selection-placeholder"
/>
</div>
<div>
<div
class="ant-select-dropdown ant-cascader-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up"
style="opacity: 0; pointer-events: none; min-width: auto;"
>
<div>
<div
class="ant-cascader-menus"
>
<ul
class="ant-cascader-menu"
role="menu"
>
<li
aria-checked="false"
class="ant-cascader-menu-item ant-cascader-menu-item-expand"
data-path-key="zhejiang"
role="menuitemcheckbox"
title="Zhejiang"
>
<span
class="ant-cascader-checkbox"
>
<span
class="ant-cascader-checkbox-inner"
/>
</span>
<div
class="ant-cascader-menu-item-content"
>
Zhejiang
</div>
<div
class="ant-cascader-menu-item-expand-icon"
>
<span
aria-label="right"
class="anticon anticon-right"
role="img"
>
<svg
aria-hidden="true"
data-icon="right"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
/>
</svg>
</span>
</div>
</li>
<li
aria-checked="false"
class="ant-cascader-menu-item ant-cascader-menu-item-expand"
data-path-key="jiangsu"
role="menuitemcheckbox"
title="Jiangsu"
>
<span
class="ant-cascader-checkbox"
>
<span
class="ant-cascader-checkbox-inner"
/>
</span>
<div
class="ant-cascader-menu-item-content"
>
Jiangsu
</div>
<div
class="ant-cascader-menu-item-expand-icon"
>
<span
aria-label="right"
class="anticon anticon-right"
role="img"
>
<svg
aria-hidden="true"
data-icon="right"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
/>
</svg>
</span>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
`;
exports[`Cascader popup correctly with defaultValue 1`] = `
<div
class="ant-select-dropdown ant-cascader-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up"

131
components/cascader/__tests__/index.test.js

@ -8,6 +8,8 @@ import focusTest from '../../../tests/shared/focusTest';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
const { SHOW_CHILD, SHOW_PARENT } = Cascader;
function toggleOpen(wrapper) {
wrapper.find('.ant-select-selector').simulate('mousedown');
}
@ -525,5 +527,134 @@ describe('Cascader', () => {
errorSpy.mockRestore();
});
it('should support showCheckedStrategy child', () => {
const multipleOptions = [
{
value: 'zhejiang',
label: 'Zhejiang',
children: [
{
value: 'hangzhou',
label: 'Hangzhou',
children: [
{
value: 'xihu',
label: 'West Lake',
},
{
value: 'donghu',
label: 'East Lake',
},
],
},
],
},
{
value: 'jiangsu',
label: 'Jiangsu',
children: [
{
value: 'nanjing',
label: 'Nanjing',
children: [
{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
},
],
},
],
},
];
let selectedValue;
const onChange = function onChange(value) {
selectedValue = value;
};
const wrapper = mount(
<Cascader
options={multipleOptions}
onChange={onChange}
multiple
showCheckedStrategy={SHOW_CHILD}
/>,
);
toggleOpen(wrapper);
expect(wrapper.render()).toMatchSnapshot();
clickOption(wrapper, 0, 0);
clickOption(wrapper, 1, 0);
clickOption(wrapper, 2, 0);
clickOption(wrapper, 2, 1);
expect(selectedValue[0].join(',')).toBe('zhejiang,hangzhou,xihu');
expect(selectedValue[1].join(',')).toBe('zhejiang,hangzhou,donghu');
expect(selectedValue.join(',')).toBe('zhejiang,hangzhou,xihu,zhejiang,hangzhou,donghu');
});
it('should support showCheckedStrategy parent', () => {
const multipleOptions = [
{
value: 'zhejiang',
label: 'Zhejiang',
children: [
{
value: 'hangzhou',
label: 'Hangzhou',
children: [
{
value: 'xihu',
label: 'West Lake',
},
{
value: 'donghu',
label: 'East Lake',
},
],
},
],
},
{
value: 'jiangsu',
label: 'Jiangsu',
children: [
{
value: 'nanjing',
label: 'Nanjing',
children: [
{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
},
],
},
],
},
];
let selectedValue;
const onChange = function onChange(value) {
selectedValue = value;
};
const wrapper = mount(
<Cascader
options={multipleOptions}
onChange={onChange}
multiple
showCheckedStrategy={SHOW_PARENT}
/>,
);
toggleOpen(wrapper);
expect(wrapper.render()).toMatchSnapshot();
clickOption(wrapper, 0, 0);
clickOption(wrapper, 1, 0);
clickOption(wrapper, 2, 0);
clickOption(wrapper, 2, 1);
expect(selectedValue.length).toBe(1);
expect(selectedValue.join(',')).toBe('zhejiang');
});
});
});

90
components/cascader/demo/showCheckedStrategy.md

@ -0,0 +1,90 @@
---
order: 5.1
version: 4.20.0
title:
zh-CN: 自定义回填方式
en-US: ShowCheckedStrategy
---
## zh-CN
通过设置 `ShowCheckedStrategy` 选择回填方式。
## en-US
The way show selected item in box using `ShowCheckedStrategy`.
```jsx
import { Cascader } from 'antd';
const { SHOW_CHILD } = Cascader;
const options = [
{
label: 'Light',
value: 'light',
children: new Array(20)
.fill(null)
.map((_, index) => ({ label: `Number ${index}`, value: index })),
},
{
label: 'Bamboo',
value: 'bamboo',
children: [
{
label: 'Little',
value: 'little',
children: [
{
label: 'Toy Fish',
value: 'fish',
},
{
label: 'Toy Cards',
value: 'cards',
},
{
label: 'Toy Bird',
value: 'bird',
},
],
},
],
},
];
const App = () => {
const onChange = value => {
console.log(value);
};
return (
<>
<Cascader
style={{ width: '100%' }}
options={options}
onChange={onChange}
multiple
maxTagCount="responsive"
showCheckedStrategy={SHOW_CHILD}
defaultValue={[
['bamboo', 'little', 'fish'],
['bamboo', 'little', 'cards'],
['bamboo', 'little', 'bird'],
]}
/>
<br />
<br />
<Cascader
style={{ width: '100%' }}
options={options}
onChange={onChange}
multiple
maxTagCount="responsive"
defaultValue={['bamboo']}
/>
</>
);
};
ReactDOM.render(<App />, mountNode);
```

3
components/cascader/index.en-US.md

@ -54,7 +54,8 @@ Cascade selection box.
| onChange | Callback when finishing cascader select | (value, selectedOptions) => void | - | |
| onDropdownVisibleChange | Callback when popup shown or hidden | (value) => void | - | 4.17.0 |
| multiple | Support multiple or not | boolean | - | 4.17.0 |
| removeIcon | The custom remove icon | ReactNode | - | |
| showCheckedStrategy | The way show selected item in box. ** `SHOW_CHILD`: ** just show child treeNode. **`Cascader.SHOW_PARENT`:** just show parent treeNode (when all child treeNode under the parent treeNode are checked) | `Cascader.SHOW_PARENT` \| `Cascader.SHOW_CHILD` | `Cascader.SHOW_PARENT` | 4.20.0 |
| removeIcon | The custom remove icon | ReactNode | - | |
| searchValue | Set search value,Need work with `showSearch` | string | - | 4.17.0 |
| onSearch | The callback function triggered when input changed | (search: string) => void | - | 4.17.0 |
| dropdownMenuColumnStyle | The style of the drop-down menu column | CSSProperties | - | |

8
components/cascader/index.tsx

@ -34,6 +34,8 @@ export type FieldNamesType = FieldNames;
export type FilledFieldNamesType = Required<FieldNamesType>;
const { SHOW_CHILD, SHOW_PARENT } = RcCascader;
function highlightKeyword(str: string, lowerKeyword: string, prefixCls: string | undefined) {
const cells = str
.toLowerCase()
@ -290,12 +292,16 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
showArrow={hasFeedback || showArrow}
/>
);
}) as (<OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType>(
}) as unknown as (<OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType>(
props: React.PropsWithChildren<CascaderProps<OptionType>> & { ref?: React.Ref<CascaderRef> },
) => React.ReactElement) & {
displayName: string;
SHOW_PARENT: typeof SHOW_PARENT;
SHOW_CHILD: typeof SHOW_CHILD;
};
Cascader.displayName = 'Cascader';
Cascader.SHOW_PARENT = SHOW_PARENT;
Cascader.SHOW_CHILD = SHOW_CHILD;
export default Cascader;

1
components/cascader/index.zh-CN.md

@ -55,6 +55,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/UdS8y8xyZ/Cascader.svg
| onChange | 选择完成后的回调 | (value, selectedOptions) => void | - | |
| onDropdownVisibleChange | 显示/隐藏浮层的回调 | (value) => void | - | 4.17.0 |
| multiple | 支持多选节点 | boolean | - | 4.17.0 |
| showCheckedStrategy | 定义选中项回填的方式。`Cascader.SHOW_CHILD`: 只显示选中的子节点。`Cascader.SHOW_PARENT`: 只显示父节点(当父节点下所有子节点都选中时)。 | `Cascader.SHOW_PARENT` \| `Cascader.SHOW_CHILD` | `Cascader.SHOW_PARENT` | 4.20.0 |
| removeIcon | 自定义的多选框清除图标 | ReactNode | - | |
| searchValue | 设置搜索的值,需要与 `showSearch` 配合使用 | string | - | 4.17.0 |
| onSearch | 监听搜索,返回输入的值 | (search: string) => void | - | 4.17.0 |

Loading…
Cancel
Save