feat(components): [cascader]add collapse-tags-tooltip (#6331)

This commit is contained in:
Alan Wang 2022-03-11 02:58:00 -05:00 committed by GitHub
parent a3e3acc0fc
commit 103bb1b104
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 115 additions and 5 deletions

View File

@ -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) | - | - |

View File

@ -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>

View File

@ -54,6 +54,7 @@ export interface Tag {
text: string
hitState?: boolean
closable: boolean
isCollapseTag: boolean
}
export interface ElCascaderPanelContext {

View File

@ -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 () => {

View File

@ -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,

View File

@ -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);
}