mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
feat(components): [cascader] add show-checked-strategy prop (#16922)
* feat(components): [cascader] add showCheckedStrategy prop * fix(components): [cascader] fix props * feat(components): [cascader] add `show-checked-strategy` documentation * Update docs/en-US/component/cascader.md Co-authored-by: btea <2356281422@qq.com> * fix(components): [cascader] replace inline props with variables --------- Co-authored-by: btea <2356281422@qq.com>
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
314
docs/examples/cascader/show-checked-strategy.vue
Normal file
314
docs/examples/cascader/show-checked-strategy.vue
Normal file
@@ -0,0 +1,314 @@
|
||||
<template>
|
||||
<div class="m-4">
|
||||
<p>Strategy: child (default, show all selected child nodes)</p>
|
||||
<el-cascader
|
||||
v-model="value1"
|
||||
:options="options"
|
||||
:props="props"
|
||||
show-checked-strategy="child"
|
||||
clearable
|
||||
@change="handleChange1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="m-4">
|
||||
<p>
|
||||
Strategy: parent (show only parent nodes when all children are selected)
|
||||
</p>
|
||||
<el-cascader
|
||||
v-model="value2"
|
||||
:options="options"
|
||||
:props="props"
|
||||
show-checked-strategy="parent"
|
||||
clearable
|
||||
@change="handleChange2"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const value1 = ref([])
|
||||
const value2 = ref([])
|
||||
const props = {
|
||||
multiple: true,
|
||||
}
|
||||
|
||||
const handleChange1 = (value) => {
|
||||
console.log('Child strategy:', value)
|
||||
}
|
||||
|
||||
const handleChange2 = (value) => {
|
||||
console.log('Parent strategy:', value)
|
||||
}
|
||||
|
||||
const options = [
|
||||
{
|
||||
value: 'guide',
|
||||
label: 'Guide',
|
||||
children: [
|
||||
{
|
||||
value: 'disciplines',
|
||||
label: 'Disciplines',
|
||||
children: [
|
||||
{
|
||||
value: 'consistency',
|
||||
label: 'Consistency',
|
||||
},
|
||||
{
|
||||
value: 'feedback',
|
||||
label: 'Feedback',
|
||||
},
|
||||
{
|
||||
value: 'efficiency',
|
||||
label: 'Efficiency',
|
||||
},
|
||||
{
|
||||
value: 'controllability',
|
||||
label: 'Controllability',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: 'navigation',
|
||||
label: 'Navigation',
|
||||
children: [
|
||||
{
|
||||
value: 'side nav',
|
||||
label: 'Side Navigation',
|
||||
},
|
||||
{
|
||||
value: 'top nav',
|
||||
label: 'Top Navigation',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: 'component',
|
||||
label: 'Component',
|
||||
children: [
|
||||
{
|
||||
value: 'basic',
|
||||
label: 'Basic',
|
||||
children: [
|
||||
{
|
||||
value: 'layout',
|
||||
label: 'Layout',
|
||||
},
|
||||
{
|
||||
value: 'color',
|
||||
label: 'Color',
|
||||
},
|
||||
{
|
||||
value: 'typography',
|
||||
label: 'Typography',
|
||||
},
|
||||
{
|
||||
value: 'icon',
|
||||
label: 'Icon',
|
||||
},
|
||||
{
|
||||
value: 'button',
|
||||
label: 'Button',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: 'form',
|
||||
label: 'Form',
|
||||
children: [
|
||||
{
|
||||
value: 'radio',
|
||||
label: 'Radio',
|
||||
},
|
||||
{
|
||||
value: 'checkbox',
|
||||
label: 'Checkbox',
|
||||
},
|
||||
{
|
||||
value: 'input',
|
||||
label: 'Input',
|
||||
},
|
||||
{
|
||||
value: 'input-number',
|
||||
label: 'InputNumber',
|
||||
},
|
||||
{
|
||||
value: 'select',
|
||||
label: 'Select',
|
||||
},
|
||||
{
|
||||
value: 'cascader',
|
||||
label: 'Cascader',
|
||||
},
|
||||
{
|
||||
value: 'switch',
|
||||
label: 'Switch',
|
||||
},
|
||||
{
|
||||
value: 'slider',
|
||||
label: 'Slider',
|
||||
},
|
||||
{
|
||||
value: 'time-picker',
|
||||
label: 'TimePicker',
|
||||
},
|
||||
{
|
||||
value: 'date-picker',
|
||||
label: 'DatePicker',
|
||||
},
|
||||
{
|
||||
value: 'datetime-picker',
|
||||
label: 'DateTimePicker',
|
||||
},
|
||||
{
|
||||
value: 'upload',
|
||||
label: 'Upload',
|
||||
},
|
||||
{
|
||||
value: 'rate',
|
||||
label: 'Rate',
|
||||
},
|
||||
{
|
||||
value: 'form',
|
||||
label: 'Form',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: 'data',
|
||||
label: 'Data',
|
||||
children: [
|
||||
{
|
||||
value: 'table',
|
||||
label: 'Table',
|
||||
},
|
||||
{
|
||||
value: 'tag',
|
||||
label: 'Tag',
|
||||
},
|
||||
{
|
||||
value: 'progress',
|
||||
label: 'Progress',
|
||||
},
|
||||
{
|
||||
value: 'tree',
|
||||
label: 'Tree',
|
||||
},
|
||||
{
|
||||
value: 'pagination',
|
||||
label: 'Pagination',
|
||||
},
|
||||
{
|
||||
value: 'badge',
|
||||
label: 'Badge',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: 'notice',
|
||||
label: 'Notice',
|
||||
children: [
|
||||
{
|
||||
value: 'alert',
|
||||
label: 'Alert',
|
||||
},
|
||||
{
|
||||
value: 'loading',
|
||||
label: 'Loading',
|
||||
},
|
||||
{
|
||||
value: 'message',
|
||||
label: 'Message',
|
||||
},
|
||||
{
|
||||
value: 'message-box',
|
||||
label: 'MessageBox',
|
||||
},
|
||||
{
|
||||
value: 'notification',
|
||||
label: 'Notification',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: 'navigation',
|
||||
label: 'Navigation',
|
||||
children: [
|
||||
{
|
||||
value: 'menu',
|
||||
label: 'Menu',
|
||||
},
|
||||
{
|
||||
value: 'tabs',
|
||||
label: 'Tabs',
|
||||
},
|
||||
{
|
||||
value: 'breadcrumb',
|
||||
label: 'Breadcrumb',
|
||||
},
|
||||
{
|
||||
value: 'dropdown',
|
||||
label: 'Dropdown',
|
||||
},
|
||||
{
|
||||
value: 'steps',
|
||||
label: 'Steps',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: 'others',
|
||||
label: 'Others',
|
||||
children: [
|
||||
{
|
||||
value: 'dialog',
|
||||
label: 'Dialog',
|
||||
},
|
||||
{
|
||||
value: 'tooltip',
|
||||
label: 'Tooltip',
|
||||
},
|
||||
{
|
||||
value: 'popover',
|
||||
label: 'Popover',
|
||||
},
|
||||
{
|
||||
value: 'card',
|
||||
label: 'Card',
|
||||
},
|
||||
{
|
||||
value: 'carousel',
|
||||
label: 'Carousel',
|
||||
},
|
||||
{
|
||||
value: 'collapse',
|
||||
label: 'Collapse',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: 'resource',
|
||||
label: 'Resource',
|
||||
children: [
|
||||
{
|
||||
value: 'axure',
|
||||
label: 'Axure Components',
|
||||
},
|
||||
{
|
||||
value: 'sketch',
|
||||
label: 'Sketch Templates',
|
||||
},
|
||||
{
|
||||
value: 'docs',
|
||||
label: 'Design Documentation',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
</script>
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -259,8 +259,8 @@ const popperOptions: Partial<Options> = {
|
||||
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[] = []
|
||||
|
||||
Reference in New Issue
Block a user