feat: tree-select add tag-render
parent
646fad2eda
commit
d46762c1d6
|
@ -27,9 +27,9 @@ Multiple and checkable.
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { TreeSelect } from 'ant-design-vue';
|
|
||||||
import type { TreeSelectProps } from 'ant-design-vue';
|
import type { TreeSelectProps } from 'ant-design-vue';
|
||||||
import { defineComponent, ref, watch } from 'vue';
|
import { defineComponent, ref, watch } from 'vue';
|
||||||
|
import { TreeSelect } from 'ant-design-vue';
|
||||||
const SHOW_PARENT = TreeSelect.SHOW_PARENT;
|
const SHOW_PARENT = TreeSelect.SHOW_PARENT;
|
||||||
|
|
||||||
const treeData: TreeSelectProps['treeData'] = [
|
const treeData: TreeSelectProps['treeData'] = [
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
<docs>
|
||||||
|
---
|
||||||
|
order: 24
|
||||||
|
title:
|
||||||
|
zh-CN: 自定义选择标签
|
||||||
|
en-US: Custom Tag Render
|
||||||
|
---
|
||||||
|
|
||||||
|
## zh-CN
|
||||||
|
|
||||||
|
允许自定义选择标签的样式。仅支持多选模式,单选可直接使用 `title` 插槽
|
||||||
|
|
||||||
|
## en-US
|
||||||
|
|
||||||
|
Allows for custom rendering of tags.
|
||||||
|
|
||||||
|
</docs>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a-tree-select
|
||||||
|
v-model:value="value"
|
||||||
|
show-search
|
||||||
|
style="width: 100%"
|
||||||
|
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||||
|
placeholder="Please select"
|
||||||
|
allow-clear
|
||||||
|
multiple
|
||||||
|
:show-checked-strategy="SHOW_ALL"
|
||||||
|
tree-default-expand-all
|
||||||
|
:tree-data="treeData"
|
||||||
|
>
|
||||||
|
<template #tagRender="{ label, closable, onClose, option }">
|
||||||
|
<a-tag :closable="closable" :color="option.color" style="margin-right: 3px" @close="onClose">
|
||||||
|
{{ label }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template #title="{ value: val, title }">
|
||||||
|
<b v-if="val === 'parent 1-1'" style="color: #08c">{{ val }}</b>
|
||||||
|
<template v-else>{{ title }}</template>
|
||||||
|
</template>
|
||||||
|
</a-tree-select>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import type { TreeSelectProps } from 'ant-design-vue';
|
||||||
|
import { defineComponent, ref, watch } from 'vue';
|
||||||
|
import { TreeSelect } from 'ant-design-vue';
|
||||||
|
const SHOW_ALL = TreeSelect.SHOW_ALL;
|
||||||
|
export default defineComponent({
|
||||||
|
setup() {
|
||||||
|
const value = ref<string[]>(['parent 1', 'parent 1-0', 'leaf1']);
|
||||||
|
const treeData = ref<TreeSelectProps['treeData']>([
|
||||||
|
{
|
||||||
|
title: 'parent 1',
|
||||||
|
value: 'parent 1',
|
||||||
|
color: 'pink',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: 'parent 1-0',
|
||||||
|
value: 'parent 1-0',
|
||||||
|
color: 'orange',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: 'my leaf',
|
||||||
|
value: 'leaf1',
|
||||||
|
color: 'green',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'your leaf',
|
||||||
|
value: 'leaf2',
|
||||||
|
color: 'cyan',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'parent 1-1',
|
||||||
|
value: 'parent 1-1',
|
||||||
|
color: 'blue',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
watch(value, () => {
|
||||||
|
console.log('select', value.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
value,
|
||||||
|
treeData,
|
||||||
|
SHOW_ALL,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -7,6 +7,9 @@
|
||||||
<suffix />
|
<suffix />
|
||||||
<async />
|
<async />
|
||||||
<Highlight />
|
<Highlight />
|
||||||
|
<treeLineVue />
|
||||||
|
<virtualScrollVue />
|
||||||
|
<customTagRenderVue />
|
||||||
</demo-sort>
|
</demo-sort>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
@ -17,6 +20,9 @@ import Checkable from './checkable.vue';
|
||||||
import Suffix from './suffix.vue';
|
import Suffix from './suffix.vue';
|
||||||
import Async from './async.vue';
|
import Async from './async.vue';
|
||||||
import Highlight from './highlight.vue';
|
import Highlight from './highlight.vue';
|
||||||
|
import treeLineVue from './tree-line.vue';
|
||||||
|
import virtualScrollVue from './virtual-scroll.vue';
|
||||||
|
import customTagRenderVue from './custom-tag-render.vue';
|
||||||
import CN from '../index.zh-CN.md';
|
import CN from '../index.zh-CN.md';
|
||||||
import US from '../index.en-US.md';
|
import US from '../index.en-US.md';
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
@ -32,6 +38,9 @@ export default defineComponent({
|
||||||
Suffix,
|
Suffix,
|
||||||
Async,
|
Async,
|
||||||
Highlight,
|
Highlight,
|
||||||
|
treeLineVue,
|
||||||
|
virtualScrollVue,
|
||||||
|
customTagRenderVue,
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -17,29 +17,31 @@ Use `treeLine` to show the line style.
|
||||||
</docs>
|
</docs>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<a-switch
|
<a-space direction="vertical">
|
||||||
v-model:checked="treeLine"
|
<a-switch
|
||||||
checked-children="treeLine"
|
v-model:checked="treeLine"
|
||||||
un-checked-children="treeLine"
|
checked-children="treeLine"
|
||||||
></a-switch>
|
un-checked-children="treeLine"
|
||||||
<a-switch
|
></a-switch>
|
||||||
v-model:checked="showLeafIcon"
|
<a-switch
|
||||||
:disabled="!treeLine"
|
v-model:checked="showLeafIcon"
|
||||||
checked-children="showLeafIcon"
|
:disabled="!treeLine"
|
||||||
un-checked-children="showLeafIcon"
|
checked-children="showLeafIcon"
|
||||||
></a-switch>
|
un-checked-children="showLeafIcon"
|
||||||
<a-tree-select
|
></a-switch>
|
||||||
v-model:value="value"
|
<a-tree-select
|
||||||
style="width: 300px"
|
v-model:value="value"
|
||||||
placeholder="Please select"
|
style="width: 300px"
|
||||||
:tree-line="treeLine && { showLeafIcon }"
|
placeholder="Please select"
|
||||||
:tree-data="treeData"
|
:tree-line="treeLine && { showLeafIcon }"
|
||||||
>
|
:tree-data="treeData"
|
||||||
<template #title="{ value: val, title }">
|
>
|
||||||
<b v-if="val === 'parent 1-1'" style="color: #08c">sss</b>
|
<template #title="{ value: val, title }">
|
||||||
<template v-else>{{ title }}</template>
|
<b v-if="val === 'parent 1-1'" style="color: #08c">sss</b>
|
||||||
</template>
|
<template v-else>{{ title }}</template>
|
||||||
</a-tree-select>
|
</template>
|
||||||
|
</a-tree-select>
|
||||||
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { TreeSelectProps } from 'ant-design-vue';
|
import type { TreeSelectProps } from 'ant-design-vue';
|
|
@ -1,74 +0,0 @@
|
||||||
<docs>
|
|
||||||
---
|
|
||||||
order: 2
|
|
||||||
title:
|
|
||||||
zh-CN: 从数据直接生成
|
|
||||||
en-US: Generate form tree data
|
|
||||||
---
|
|
||||||
|
|
||||||
## zh-CN
|
|
||||||
|
|
||||||
使用 `treeData` 把 JSON 数据直接生成树结构。
|
|
||||||
|
|
||||||
## en-US
|
|
||||||
|
|
||||||
The tree structure can be populated using `treeData` property. This is a quick and easy way to provide the tree content.
|
|
||||||
|
|
||||||
</docs>
|
|
||||||
<template>
|
|
||||||
<a-tree-select
|
|
||||||
v-model:value="value"
|
|
||||||
style="width: 100%"
|
|
||||||
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
|
||||||
:tree-data="treeData"
|
|
||||||
placeholder="Please select"
|
|
||||||
tree-default-expand-all
|
|
||||||
>
|
|
||||||
<template #title="{ key, value: val, title }">
|
|
||||||
<span v-if="key === '0-0-1'" style="color: #08c">Child Node1 {{ val }}</span>
|
|
||||||
<template v-else>{{ title }}</template>
|
|
||||||
</template>
|
|
||||||
</a-tree-select>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import type { TreeSelectProps } from 'ant-design-vue';
|
|
||||||
import { defineComponent, ref, watch } from 'vue';
|
|
||||||
|
|
||||||
const treeData: TreeSelectProps['treeData'] = [
|
|
||||||
{
|
|
||||||
title: 'Node1',
|
|
||||||
value: '0-0',
|
|
||||||
key: '0-0',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
value: '0-0-1',
|
|
||||||
key: '0-0-1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Child Node2',
|
|
||||||
value: '0-0-2',
|
|
||||||
key: '0-0-2',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Node2',
|
|
||||||
value: '0-1',
|
|
||||||
key: '0-1',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
export default defineComponent({
|
|
||||||
setup() {
|
|
||||||
const value = ref<string>();
|
|
||||||
|
|
||||||
watch(value, () => {
|
|
||||||
console.log(value.value);
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
value,
|
|
||||||
treeData,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
<docs>
|
||||||
|
---
|
||||||
|
order: 9
|
||||||
|
title:
|
||||||
|
zh-CN: 虚拟滚动
|
||||||
|
en-US: Virtual scroll
|
||||||
|
---
|
||||||
|
|
||||||
|
## zh-CN
|
||||||
|
|
||||||
|
使用 `height` 属性则切换为虚拟滚动。
|
||||||
|
|
||||||
|
## en-US
|
||||||
|
|
||||||
|
Use virtual list through `height` prop.
|
||||||
|
|
||||||
|
</docs>
|
||||||
|
<template>
|
||||||
|
<a-tree-select
|
||||||
|
v-model:value="checkedKeys"
|
||||||
|
style="width: 100%"
|
||||||
|
tree-checkable
|
||||||
|
tree-default-expand-all
|
||||||
|
:show-checked-strategy="SHOW_PARENT"
|
||||||
|
:height="233"
|
||||||
|
:tree-data="treeData"
|
||||||
|
:max-tag-count="10"
|
||||||
|
>
|
||||||
|
<template #title="{ title, value }">
|
||||||
|
<span v-if="value === '0-0-1-0'" style="color: #1890ff">{{ title }}</span>
|
||||||
|
<template v-else>{{ title }}</template>
|
||||||
|
</template>
|
||||||
|
</a-tree-select>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import type { TreeSelectProps } from 'ant-design-vue';
|
||||||
|
import { TreeSelect } from 'ant-design-vue';
|
||||||
|
import { defineComponent, ref, watch } from 'vue';
|
||||||
|
const SHOW_PARENT = TreeSelect.SHOW_PARENT;
|
||||||
|
|
||||||
|
function dig(path = '0', level = 3) {
|
||||||
|
const list: TreeSelectProps['treeData'] = [];
|
||||||
|
for (let i = 0; i < 10; i += 1) {
|
||||||
|
const value = `${path}-${i}`;
|
||||||
|
const treeNode: TreeSelectProps['treeData'][number] = {
|
||||||
|
title: value,
|
||||||
|
value,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (level > 0) {
|
||||||
|
treeNode.children = dig(value, level - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
list.push(treeNode);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
setup() {
|
||||||
|
const checkedKeys = ref<string[]>(['0-0-0', '0-0-1']);
|
||||||
|
watch(checkedKeys, () => {
|
||||||
|
console.log('checkedKeys', checkedKeys);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
treeData: dig(),
|
||||||
|
checkedKeys,
|
||||||
|
SHOW_PARENT,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -10,6 +10,7 @@ import type { VueNode } from '../../_util/type';
|
||||||
import Overflow from '../../vc-overflow';
|
import Overflow from '../../vc-overflow';
|
||||||
import type { DisplayValueType, RenderNode, CustomTagProps, RawValueType } from '../BaseSelect';
|
import type { DisplayValueType, RenderNode, CustomTagProps, RawValueType } from '../BaseSelect';
|
||||||
import type { BaseOptionType } from '../Select';
|
import type { BaseOptionType } from '../Select';
|
||||||
|
import useInjectLegacySelectContext from '../../vc-tree-select/LegacyContext';
|
||||||
|
|
||||||
type SelectorProps = InnerSelectorProps & {
|
type SelectorProps = InnerSelectorProps & {
|
||||||
// Icon
|
// Icon
|
||||||
|
@ -79,7 +80,7 @@ const SelectSelector = defineComponent<SelectorProps>({
|
||||||
const measureRef = ref();
|
const measureRef = ref();
|
||||||
const inputWidth = ref(0);
|
const inputWidth = ref(0);
|
||||||
const focused = ref(false);
|
const focused = ref(false);
|
||||||
|
const legacyTreeSelectContext = useInjectLegacySelectContext();
|
||||||
const selectionPrefixCls = computed(() => `${props.prefixCls}-selection`);
|
const selectionPrefixCls = computed(() => `${props.prefixCls}-selection`);
|
||||||
|
|
||||||
// ===================== Search ======================
|
// ===================== Search ======================
|
||||||
|
@ -147,15 +148,20 @@ const SelectSelector = defineComponent<SelectorProps>({
|
||||||
onPreventMouseDown(e);
|
onPreventMouseDown(e);
|
||||||
props.onToggleOpen(!open);
|
props.onToggleOpen(!open);
|
||||||
};
|
};
|
||||||
|
let originData = option;
|
||||||
|
// For TreeSelect
|
||||||
|
if (legacyTreeSelectContext.keyEntities) {
|
||||||
|
originData = legacyTreeSelectContext.keyEntities[value]?.node || {};
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<span onMousedown={onMouseDown}>
|
<span key={value} onMousedown={onMouseDown}>
|
||||||
{props.tagRender({
|
{props.tagRender({
|
||||||
label: content,
|
label: content,
|
||||||
value,
|
value,
|
||||||
disabled: itemDisabled,
|
disabled: itemDisabled,
|
||||||
closable,
|
closable,
|
||||||
onClose,
|
onClose,
|
||||||
option,
|
option: originData,
|
||||||
})}
|
})}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
|
@ -109,6 +109,7 @@ const SingleSelector = defineComponent<SelectorProps>({
|
||||||
let titleNode = null;
|
let titleNode = null;
|
||||||
// custom tree-select title by slot
|
// custom tree-select title by slot
|
||||||
|
|
||||||
|
// For TreeSelect
|
||||||
if (item && legacyTreeSelectContext.customSlots) {
|
if (item && legacyTreeSelectContext.customSlots) {
|
||||||
const key = item.key ?? item.value;
|
const key = item.key ?? item.value;
|
||||||
const originData = legacyTreeSelectContext.keyEntities[key]?.node || {};
|
const originData = legacyTreeSelectContext.keyEntities[key]?.node || {};
|
||||||
|
|
|
@ -727,6 +727,7 @@ export default defineComponent({
|
||||||
OptionList={OptionList}
|
OptionList={OptionList}
|
||||||
emptyOptions={!mergedTreeData.value.length}
|
emptyOptions={!mergedTreeData.value.length}
|
||||||
onDropdownVisibleChange={onInternalDropdownVisibleChange}
|
onDropdownVisibleChange={onInternalDropdownVisibleChange}
|
||||||
|
tagRender={props.tagRender || slots.tagRender}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue