diff --git a/docs/en-US/component/cascader.md b/docs/en-US/component/cascader.md index bb5cc3424f..c7f8a174aa 100644 --- a/docs/en-US/component/cascader.md +++ b/docs/en-US/component/cascader.md @@ -168,6 +168,16 @@ cascader/check-on-click-node ::: +## Show Checked Strategy + +Control how selected values are displayed in multiple selection mode. + +:::demo In multiple selection mode, you can use `show-checked-strategy` to control how selected values are displayed. The default strategy is `child`, which shows all selected child nodes. The `parent` strategy only shows parent nodes when all their children are selected. + +cascader/show-checked-strategy + +::: + ## Cascader API ### Cascader Attributes @@ -202,6 +212,7 @@ cascader/check-on-click-node | fallback-placements ^(2.8.1) | list of possible positions for Tooltip [popper.js](https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements) | ^[arrary]`Placement[]` | — | | placement ^(2.8.1) | position of dropdown | ^[enum]`'top' \| 'top-start' \| 'top-end' \| 'bottom' \| 'bottom-start' \| 'bottom-end' \| 'left' \| 'left-start' \| 'left-end' \| 'right' \| 'right-start' \| 'right-end'` | bottom-start | | popper-append-to-body ^(deprecated) | whether to append the popper menu to body. If the positioning of the popper is wrong, you can try to set this prop to false | ^[boolean] | true | +| show-checked-strategy ^(2.10.5) | strategy for displaying checked nodes in multiple selection mode. Use `parent` when you want things tidy. Use `child` when every single item matters | ^[enum]`'parent' \| 'child'` | child | ### Cascader Events diff --git a/docs/examples/cascader/show-checked-strategy.vue b/docs/examples/cascader/show-checked-strategy.vue new file mode 100644 index 0000000000..e185757f7c --- /dev/null +++ b/docs/examples/cascader/show-checked-strategy.vue @@ -0,0 +1,314 @@ + + + diff --git a/packages/components/cascader/src/cascader.ts b/packages/components/cascader/src/cascader.ts index 3779716094..43b03f72a3 100644 --- a/packages/components/cascader/src/cascader.ts +++ b/packages/components/cascader/src/cascader.ts @@ -142,6 +142,15 @@ export const cascaderProps = buildProps({ type: Boolean, default: true, }, + /** + * @description Use `parent` when you want things tidy (like "Entire Collection" instead of listing 100 items) + * Use `child` when every single item matters (like important settings) + */ + showCheckedStrategy: { + type: String, + values: ['parent', 'child'], + default: 'child', + }, /** * @description whether to check or uncheck node when clicking on the node */ diff --git a/packages/components/cascader/src/cascader.vue b/packages/components/cascader/src/cascader.vue index a3e9dbdb22..70bc8ec15d 100644 --- a/packages/components/cascader/src/cascader.vue +++ b/packages/components/cascader/src/cascader.vue @@ -259,8 +259,8 @@ const popperOptions: Partial = { name: 'arrowPosition', enabled: true, phase: 'main', - fn: ({ state }) => { - const { modifiersData, placement } = state as any + fn: ({ state }: any) => { + const { modifiersData, placement } = state if (['right', 'left', 'bottom', 'top'].includes(placement)) return if (modifiersData.arrow) { modifiersData.arrow.x = 35 @@ -447,10 +447,27 @@ const deleteTag = (tag: Tag) => { emit('removeTag', node.valueByOption) } +const getStrategyCheckedNodes = (): CascaderNode[] => { + switch (props.showCheckedStrategy) { + case 'child': + return checkedNodes.value + case 'parent': { + const clickedNodes = getCheckedNodes(false) + const clickedNodesValue = clickedNodes!.map((o) => o.value) + const parentNodes = clickedNodes!.filter( + (o) => !o.parent || !clickedNodesValue.includes(o.parent.value) + ) + return parentNodes + } + default: + return [] + } +} + const calculatePresentTags = () => { if (!multiple.value) return - const nodes = checkedNodes.value + const nodes = getStrategyCheckedNodes() const tags: Tag[] = [] const allTags: Tag[] = []