feat: tree-select add tag-render

refactor-cascader
tangjinzhou 2022-01-16 11:13:39 +08:00
parent 646fad2eda
commit d46762c1d6
9 changed files with 212 additions and 101 deletions

View File

@ -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'] = [

View File

@ -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 }}&nbsp;&nbsp;
</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>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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