mirror of
https://github.com/element-plus/element-plus.git
synced 2024-11-21 01:02:59 +08:00
feat(components): [cascader]add collapse-tags-tooltip (#6331)
This commit is contained in:
parent
a3e3acc0fc
commit
103bb1b104
@ -80,7 +80,7 @@ Don't do:
|
||||
</template>
|
||||
```
|
||||
|
||||
:::demo When using multiple selection, all selected tags will display by default, You can set `collapse-tags = true` to fold selected tags.
|
||||
:::demo When using multiple selection, all selected tags will display by default. You can set `collapse-tags = true` to fold selected tags. You can check them when mouse hover collapse text by using `collapse-tags-tooltip` attribute.
|
||||
|
||||
cascader/multiple-selection
|
||||
|
||||
@ -149,6 +149,7 @@ cascader/panel
|
||||
| clearable | whether selected value can be cleared | boolean | — | false |
|
||||
| show-all-levels | whether to display all levels of the selected value in the input | boolean | — | true |
|
||||
| collapse-tags | whether to collapse tags in multiple selection mode | boolean | - | false |
|
||||
| collapse-tags-tooltip | whether show all selected tags when mouse hover text of collapse-tags. To use this, `collapse-tags` must be true | boolean | - | false |
|
||||
| separator | option label separator | string | — | ' / ' |
|
||||
| filterable | whether the options can be searched | boolean | — | — |
|
||||
| filter-method | customize search logic, the first parameter is `node`, the second is `keyword`, and need return a boolean value indicating whether it hits. | function(node, keyword) | - | - |
|
||||
|
@ -7,6 +7,16 @@
|
||||
<span class="example-demonstration">Collapse tags</span>
|
||||
<el-cascader :options="options" :props="props" collapse-tags clearable />
|
||||
</div>
|
||||
<div class="example-block">
|
||||
<span class="example-demonstration">Collapse tags tooltip</span>
|
||||
<el-cascader
|
||||
:options="options"
|
||||
:props="props"
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -54,6 +54,7 @@ export interface Tag {
|
||||
text: string
|
||||
hitState?: boolean
|
||||
closable: boolean
|
||||
isCollapseTag: boolean
|
||||
}
|
||||
|
||||
export interface ElCascaderPanelContext {
|
||||
|
@ -4,6 +4,7 @@ import { EVENT_CODE } from '@element-plus/constants'
|
||||
import { triggerEvent } from '@element-plus/test-utils'
|
||||
import { ArrowDown, Check, CircleClose } from '@element-plus/icons-vue'
|
||||
import { POPPER_CONTAINER_SELECTOR } from '@element-plus/hooks'
|
||||
import { hasClass } from '@element-plus/utils'
|
||||
import Cascader from '../src/index.vue'
|
||||
|
||||
jest.mock('lodash-unified', () => {
|
||||
@ -30,6 +31,10 @@ const OPTIONS = [
|
||||
value: 'ningbo',
|
||||
label: 'Ningbo',
|
||||
},
|
||||
{
|
||||
value: 'wenzhou',
|
||||
label: 'Wenzhou',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
@ -241,13 +246,40 @@ describe('Cascader.vue', () => {
|
||||
modelValue: [
|
||||
['zhejiang', 'hangzhou'],
|
||||
['zhejiang', 'ningbo'],
|
||||
['zhejiang', 'wenzhou'],
|
||||
],
|
||||
},
|
||||
})
|
||||
await nextTick()
|
||||
const [firstTag, secondTag] = wrapper.findAll(TAG)
|
||||
expect(firstTag.text()).toBe('Zhejiang / Hangzhou')
|
||||
expect(secondTag.text()).toBe('+ 1')
|
||||
const tags = wrapper.findAll(TAG).filter((item) => {
|
||||
return !hasClass(item.element, 'in-tooltip')
|
||||
})
|
||||
expect(tags[0].text()).toBe('Zhejiang / Hangzhou')
|
||||
expect(tags.length).toBe(2)
|
||||
})
|
||||
|
||||
test('collapse tags tooltip', async () => {
|
||||
const wrapper = mount(Cascader, {
|
||||
props: {
|
||||
options: OPTIONS,
|
||||
props: { multiple: true },
|
||||
collapseTags: true,
|
||||
collapseTagsTooltip: true,
|
||||
modelValue: [
|
||||
['zhejiang', 'hangzhou'],
|
||||
['zhejiang', 'ningbo'],
|
||||
['zhejiang', 'wenzhou'],
|
||||
],
|
||||
},
|
||||
})
|
||||
await nextTick()
|
||||
expect(wrapper.findAll(TAG).length).toBe(5)
|
||||
const tags = wrapper.findAll(TAG).filter((item) => {
|
||||
return hasClass(item.element, 'in-tooltip')
|
||||
})
|
||||
expect(tags[0].text()).toBe('Zhejiang / Hangzhou')
|
||||
expect(tags[1].text()).toBe('Zhejiang / Ningbo')
|
||||
expect(tags[2].text()).toBe('Zhejiang / Wenzhou')
|
||||
})
|
||||
|
||||
test('filterable', async () => {
|
||||
|
@ -88,7 +88,44 @@
|
||||
disable-transitions
|
||||
@close="deleteTag(tag)"
|
||||
>
|
||||
<span>{{ tag.text }}</span>
|
||||
<template v-if="tag.isCollapseTag === false">
|
||||
<span>{{ tag.text }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-tooltip
|
||||
:teleported="false"
|
||||
:disabled="popperVisible || !collapseTagsTooltip"
|
||||
:fallback-placements="['bottom', 'top', 'right', 'left']"
|
||||
placement="bottom"
|
||||
effect="light"
|
||||
>
|
||||
<template #default>
|
||||
<span>{{ tag.text }}</span>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="el-cascader__collapse-tags">
|
||||
<div
|
||||
v-for="(tag2, idx) in allPresentTags"
|
||||
:key="idx"
|
||||
class="el-cascader__collapse-tag"
|
||||
>
|
||||
<el-tag
|
||||
:key="tag2.key"
|
||||
class="in-tooltip"
|
||||
type="info"
|
||||
:size="tagSize"
|
||||
:hit="tag2.hitState"
|
||||
:closable="tag2.closable"
|
||||
disable-transitions
|
||||
@close="deleteTag(tag2)"
|
||||
>
|
||||
<span>{{ tag2.text }}</span>
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-tag>
|
||||
<input
|
||||
v-if="filterable && !isDisabled"
|
||||
@ -286,6 +323,10 @@ export default defineComponent({
|
||||
default: true,
|
||||
},
|
||||
collapseTags: Boolean,
|
||||
collapseTagsTooltip: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
debounce: {
|
||||
type: Number,
|
||||
default: 300,
|
||||
@ -341,6 +382,7 @@ export default defineComponent({
|
||||
const inputValue = ref('')
|
||||
const searchInputValue = ref('')
|
||||
const presentTags: Ref<Tag[]> = ref([])
|
||||
const allPresentTags: Ref<Tag[]> = ref([])
|
||||
const suggestions: Ref<CascaderNode[]> = ref([])
|
||||
const isOnComposition = ref(false)
|
||||
|
||||
@ -436,6 +478,7 @@ export default defineComponent({
|
||||
text: node.calcText(showAllLevels, separator),
|
||||
hitState: false,
|
||||
closable: !isDisabled.value && !node.isDisabled,
|
||||
isCollapseTag: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -452,6 +495,10 @@ export default defineComponent({
|
||||
const nodes = checkedNodes.value
|
||||
const tags: Tag[] = []
|
||||
|
||||
const allTags: Tag[] = []
|
||||
nodes.forEach((node) => allTags.push(genTag(node)))
|
||||
allPresentTags.value = allTags
|
||||
|
||||
if (nodes.length) {
|
||||
const [first, ...rest] = nodes
|
||||
const restCount = rest.length
|
||||
@ -464,6 +511,7 @@ export default defineComponent({
|
||||
key: -1,
|
||||
text: `+ ${restCount}`,
|
||||
closable: false,
|
||||
isCollapseTag: true,
|
||||
})
|
||||
} else {
|
||||
rest.forEach((node) => tags.push(genTag(node)))
|
||||
@ -488,6 +536,9 @@ export default defineComponent({
|
||||
presentTags.value.forEach((tag) => {
|
||||
tag.hitState = false
|
||||
})
|
||||
allPresentTags.value.forEach((tag) => {
|
||||
tag.hitState = false
|
||||
})
|
||||
}
|
||||
|
||||
filtering.value = true
|
||||
@ -701,6 +752,7 @@ export default defineComponent({
|
||||
inputValue,
|
||||
searchInputValue,
|
||||
presentTags,
|
||||
allPresentTags,
|
||||
suggestions,
|
||||
isDisabled,
|
||||
isOnComposition,
|
||||
|
@ -149,6 +149,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
@include e(collapse-tags) {
|
||||
white-space: normal;
|
||||
z-index: var(--el-index-normal);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
@include e(collapse-tag) {
|
||||
line-height: inherit;
|
||||
height: inherit;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@include e(suggestion-panel) {
|
||||
border-radius: var(--el-cascader-menu-radius);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user