feat(components): [select]add collapse-tags-tooltip (#6245)

* feat(components): [select]add collapse-tags-tooltip

* feat(components): [select] collapse-tags-tooltip set width

* feat(components): [select] collapse-tags-tooltip set fallback-placements

* feat(components): [select] resolve conflicts

* feat(components): [select] add v-if on tooltip
This commit is contained in:
Alan Wang
2022-03-11 02:56:23 -05:00
committed by GitHub
parent 61c6b97183
commit 57d08f9a78
5 changed files with 188 additions and 34 deletions

View File

@ -47,7 +47,7 @@ select/clearable
Multiple select uses tags to display selected options.
:::demo Set `multiple` attribute for `el-select` to enable multiple mode. In this case, the value of `v-model` will be an array of selected options. By default the selected options will be displayed as Tags. You can collapse them to a text by using `collapse-tags` attribute.
:::demo Set `multiple` attribute for `el-select` to enable multiple mode. In this case, the value of `v-model` will be an array of selected options. By default the selected options will be displayed as Tags. You can collapse them to a text by using `collapse-tags` attribute. You can check them when mouse hover collapse text by using `collapse-tags-tooltip` attribute.
select/multiple
@ -120,6 +120,7 @@ If the binding value of Select is an object, make sure to assign `value-key` as
| size | size of Input | string | large/default/small | default |
| clearable | whether select can be cleared | boolean | — | false |
| collapse-tags | whether to collapse tags to a text when multiple selecting | 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 | true / false | false |
| multiple-limit | maximum number of options user can select when `multiple` is `true`. No limit when set to 0 | number | — | 0 |
| name | the name attribute of select input | string | — | — |
| effect | Tooltip theme, built-in theme: `dark` / `light` | string | string | light |

View File

@ -1,34 +1,58 @@
<template>
<el-select
v-model="value1"
multiple
placeholder="Select"
style="width: 240px"
>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
<div style="display: inline-block">
<p style="margin-left: 10px">default</p>
<el-select
v-model="value1"
multiple
placeholder="Select"
style="width: 240px"
>
</el-option>
</el-select>
<el-select
v-model="value2"
multiple
collapse-tags
style="margin-left: 20px; width: 240px"
placeholder="Select"
>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</div>
<div style="display: inline-block; margin-left: 20px">
<p style="margin-left: 10px">use collapse-tags</p>
<el-select
v-model="value2"
multiple
collapse-tags
placeholder="Select"
style="width: 240px"
>
</el-option>
</el-select>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</div>
<div style="display: inline-block; margin-left: 20px">
<p style="margin-left: 10px">use collapse-tags-tooltip</p>
<el-select
v-model="value3"
multiple
collapse-tags
collapse-tags-tooltip
placeholder="Select"
style="width: 240px"
>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</div>
</template>
<script lang="ts" setup>
@ -36,6 +60,7 @@ import { ref } from 'vue'
const value1 = ref([])
const value2 = ref([])
const value3 = ref([])
const options = [
{
value: 'Option1',

View File

@ -3,6 +3,7 @@ import { mount } from '@vue/test-utils'
import { EVENT_CODE } from '@element-plus/constants'
import { CircleClose, ArrowUp, CaretTop } from '@element-plus/icons-vue'
import { POPPER_CONTAINER_SELECTOR } from '@element-plus/hooks'
import { hasClass } from '@element-plus/utils'
import Select from '../src/select.vue'
import Group from '../src/option-group.vue'
import Option from '../src/option.vue'
@ -920,6 +921,56 @@ describe('Select', () => {
mockInputWidth.mockRestore()
})
test('multiple select with collapseTagsTooltip', async () => {
wrapper = _mount(
`
<el-select v-model="selectedList" multiple collapseTags collapse-tags-tooltip placeholder="请选择">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
`,
() => ({
options: [
{
value: '选项1',
label: '黄金糕',
},
{
value: '选项2',
label: '双皮奶',
},
{
value: '选项3',
label: '蚵仔煎',
},
{
value: '选项4',
label: '龙须面',
},
{
value: '选项5',
label: '北京烤鸭',
},
],
selectedList: [],
})
)
await wrapper.find('.select-trigger').trigger('click')
const options = getOptions()
options[0].click()
await nextTick()
options[1].click()
await nextTick()
options[2].click()
await nextTick()
const triggerWrappers = wrapper.findAll('.el-tooltip__trigger')
expect(triggerWrappers[0]).toBeDefined()
const tags = wrapper.findAll('.el-select__tags-text')
expect(tags.length).toBe(5)
expect(tags[4].element.textContent).toBe('蚵仔煎')
})
test('multiple remove-tag', async () => {
wrapper = _mount(
`
@ -1435,9 +1486,17 @@ describe('Select', () => {
vm.isCollapsed = true
vm.isClearable = false
await nextTick()
expect(wrapper.findAll('.el-tag').length).toBe(2)
expect(
wrapper.findAll('.el-tag').filter((item) => {
return !hasClass(item.element, 'in-tooltip')
}).length
).toBe(2)
await wrapper.find('.el-tag__close').trigger('click')
expect(wrapper.findAll('.el-tag').length).toBe(2)
expect(
wrapper.findAll('.el-tag').filter((item) => {
return !hasClass(item.element, 'in-tooltip')
}).length
).toBe(2)
expect(wrapper.findAll('.el-tag__close').length).toBe(0)
// test for collapse select if is clearable
@ -1445,9 +1504,17 @@ describe('Select', () => {
vm.isCollapsed = true
vm.isClearable = true
await nextTick()
expect(wrapper.findAll('.el-tag__close').length).toBe(1)
expect(
wrapper.findAll('.el-tag__close').filter((item) => {
return !hasClass(item.element.parentElement, 'in-tooltip')
}).length
).toBe(1)
await wrapper.find('.el-tag__close').trigger('click')
expect(wrapper.findAll('.el-tag').length).toBe(2)
expect(
wrapper.findAll('.el-tag').filter((item) => {
return !hasClass(item.element, 'in-tooltip')
}).length
).toBe(2)
expect(wrapper.findAll('.el-tag__close').length).toBe(0)
})

View File

@ -57,7 +57,50 @@
:type="tagType"
disable-transitions
>
<span :class="nsSelect.e('tags-text')"
<el-tooltip
v-if="collapseTagsTooltip"
:disabled="dropMenuVisible"
:fallback-placements="['bottom', 'top', 'right', 'left']"
:effect="effect"
placement="bottom"
:teleported="false"
>
<template #default>
<span :class="nsSelect.e('tags-text')"
>+ {{ selected.length - 1 }}</span
>
</template>
<template #content>
<div :class="nsSelect.e('collapse-tags')">
<div
v-for="(item, idx) in selected"
:key="idx"
:class="nsSelect.e('collapse-tag')"
>
<el-tag
:key="getValueKey(item)"
class="in-tooltip"
:closable="!selectDisabled && !item.isDisabled"
:size="collapseTagSize"
:hit="item.hitState"
:type="tagType"
disable-transitions
:style="{ margin: '2px' }"
@close="deleteTag($event, item)"
>
<span
:class="nsSelect.e('tags-text')"
:style="{
maxWidth: inputWidth - 75 + 'px',
}"
>{{ item.currentLabel }}</span
>
</el-tag>
</div>
</div>
</template>
</el-tooltip>
<span v-else :class="nsSelect.e('tags-text')"
>+ {{ selected.length - 1 }}</span
>
</el-tag>
@ -322,6 +365,10 @@ export default defineComponent({
default: 'value',
},
collapseTags: Boolean,
collapseTagsTooltip: {
type: Boolean,
default: false,
},
popperAppendToBody: {
type: Boolean,
default: undefined,

View File

@ -159,6 +159,20 @@
flex-wrap: wrap;
}
@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;
}
.#{$namespace}-select__tags {
.#{$namespace}-tag {
box-sizing: border-box;