refactor: tree-select
parent
1581943eb0
commit
76ee4d6856
|
@ -17,7 +17,13 @@ const initDefaultProps = <T>(
|
||||||
Object.keys(defaultProps).forEach(k => {
|
Object.keys(defaultProps).forEach(k => {
|
||||||
const prop = propTypes[k] as VueTypeValidableDef;
|
const prop = propTypes[k] as VueTypeValidableDef;
|
||||||
if (prop) {
|
if (prop) {
|
||||||
prop.default = defaultProps[k];
|
if (prop.type || prop.default) {
|
||||||
|
prop.default = defaultProps[k];
|
||||||
|
} else if (prop.def) {
|
||||||
|
prop.def(defaultProps[k]);
|
||||||
|
} else {
|
||||||
|
propTypes[k] = { type: prop, default: defaultProps[k] };
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`not have ${k} prop`);
|
throw new Error(`not have ${k} prop`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,6 @@ import VcTreeSelect, {
|
||||||
import classNames from '../_util/classNames';
|
import classNames from '../_util/classNames';
|
||||||
import initDefaultProps from '../_util/props-util/initDefaultProps';
|
import initDefaultProps from '../_util/props-util/initDefaultProps';
|
||||||
import type { SizeType } from '../config-provider';
|
import type { SizeType } from '../config-provider';
|
||||||
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
|
|
||||||
import CaretDownOutlined from '@ant-design/icons-vue/CaretDownOutlined';
|
|
||||||
import type { DefaultValueType, FieldNames } from '../vc-tree-select/interface';
|
import type { DefaultValueType, FieldNames } from '../vc-tree-select/interface';
|
||||||
import omit from '../_util/omit';
|
import omit from '../_util/omit';
|
||||||
import PropTypes from '../_util/vue-types';
|
import PropTypes from '../_util/vue-types';
|
||||||
|
@ -237,78 +235,6 @@ const TreeSelect = defineComponent({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
|
||||||
saveTreeSelect(node: any) {
|
|
||||||
this.vcTreeSelect = node;
|
|
||||||
},
|
|
||||||
focus() {
|
|
||||||
this.vcTreeSelect.focus();
|
|
||||||
},
|
|
||||||
|
|
||||||
blur() {
|
|
||||||
this.vcTreeSelect.blur();
|
|
||||||
},
|
|
||||||
renderSwitcherIcon(prefixCls: string, { isLeaf, loading }) {
|
|
||||||
if (loading) {
|
|
||||||
return <LoadingOutlined class={`${prefixCls}-switcher-loading-icon`} />;
|
|
||||||
}
|
|
||||||
if (isLeaf) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return <CaretDownOutlined class={`${prefixCls}-switcher-icon`} />;
|
|
||||||
},
|
|
||||||
handleChange(...args: any[]) {
|
|
||||||
this.$emit('update:value', args[0]);
|
|
||||||
this.$emit('change', ...args);
|
|
||||||
},
|
|
||||||
handleTreeExpand(...args: any[]) {
|
|
||||||
this.$emit('update:treeExpandedKeys', args[0]);
|
|
||||||
this.$emit('treeExpand', ...args);
|
|
||||||
},
|
|
||||||
handleSearch(...args: any[]) {
|
|
||||||
this.$emit('update:searchValue', args[0]);
|
|
||||||
this.$emit('search', ...args);
|
|
||||||
},
|
|
||||||
updateTreeData(treeData: any[]) {
|
|
||||||
const { $slots } = this;
|
|
||||||
const defaultFields = {
|
|
||||||
children: 'children',
|
|
||||||
title: 'title',
|
|
||||||
key: 'key',
|
|
||||||
label: 'label',
|
|
||||||
value: 'value',
|
|
||||||
};
|
|
||||||
const replaceFields = { ...defaultFields, ...this.$props.replaceFields };
|
|
||||||
return treeData.map(item => {
|
|
||||||
const { slots = {} } = item;
|
|
||||||
const label = item[replaceFields.label];
|
|
||||||
const title = item[replaceFields.title];
|
|
||||||
const value = item[replaceFields.value];
|
|
||||||
const key = item[replaceFields.key];
|
|
||||||
const children = item[replaceFields.children];
|
|
||||||
let newLabel = typeof label === 'function' ? label() : label;
|
|
||||||
let newTitle = typeof title === 'function' ? title() : title;
|
|
||||||
if (!newLabel && slots.label && $slots[slots.label]) {
|
|
||||||
newLabel = <>{$slots[slots.label](item)}</>;
|
|
||||||
}
|
|
||||||
if (!newTitle && slots.title && $slots[slots.title]) {
|
|
||||||
newTitle = <>{$slots[slots.title](item)}</>;
|
|
||||||
}
|
|
||||||
const treeNodeProps = {
|
|
||||||
...item,
|
|
||||||
title: newTitle || newLabel,
|
|
||||||
value,
|
|
||||||
dataRef: item,
|
|
||||||
key,
|
|
||||||
};
|
|
||||||
if (children) {
|
|
||||||
return { ...treeNodeProps, children: this.updateTreeData(children) };
|
|
||||||
}
|
|
||||||
return treeNodeProps;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
|
|
|
@ -8,6 +8,7 @@ import PropTypes from '../_util/vue-types';
|
||||||
import { filterEmpty } from '../_util/props-util';
|
import { filterEmpty } from '../_util/props-util';
|
||||||
import initDefaultProps from '../_util/props-util/initDefaultProps';
|
import initDefaultProps from '../_util/props-util/initDefaultProps';
|
||||||
import type { DataNode, DragNodeEvent, FieldNames, Key } from '../vc-tree/interface';
|
import type { DataNode, DragNodeEvent, FieldNames, Key } from '../vc-tree/interface';
|
||||||
|
import type { TreeNodeProps } from '../vc-tree/props';
|
||||||
import { treeProps as vcTreeProps } from '../vc-tree/props';
|
import { treeProps as vcTreeProps } from '../vc-tree/props';
|
||||||
import useConfigInject from '../_util/hooks/useConfigInject';
|
import useConfigInject from '../_util/hooks/useConfigInject';
|
||||||
import renderSwitcherIcon from './utils/iconUtil';
|
import renderSwitcherIcon from './utils/iconUtil';
|
||||||
|
@ -35,7 +36,7 @@ export interface AntdTreeNodeAttribute {
|
||||||
disableCheckbox: boolean;
|
disableCheckbox: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AntTreeNodeProps = DataNode;
|
export type AntTreeNodeProps = TreeNodeProps;
|
||||||
|
|
||||||
// [Legacy] Compatible for v2
|
// [Legacy] Compatible for v2
|
||||||
export type TreeDataItem = DataNode;
|
export type TreeDataItem = DataNode;
|
||||||
|
|
|
@ -11,7 +11,6 @@ export {
|
||||||
AntTreeNodeCheckedEvent,
|
AntTreeNodeCheckedEvent,
|
||||||
AntTreeNodeSelectedEvent,
|
AntTreeNodeSelectedEvent,
|
||||||
AntdTreeNodeAttribute,
|
AntdTreeNodeAttribute,
|
||||||
AntTreeNodeProps,
|
|
||||||
TreeDataItem,
|
TreeDataItem,
|
||||||
} from './Tree';
|
} from './Tree';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { DataNode, Key } from 'ant-design-vue/es/vc-tree/interface';
|
import type { DataNode, Key } from '../../vc-tree/interface';
|
||||||
|
|
||||||
enum Record {
|
enum Record {
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -4,7 +4,7 @@ import MinusSquareOutlined from '@ant-design/icons-vue/MinusSquareOutlined';
|
||||||
import PlusSquareOutlined from '@ant-design/icons-vue/PlusSquareOutlined';
|
import PlusSquareOutlined from '@ant-design/icons-vue/PlusSquareOutlined';
|
||||||
import CaretDownFilled from '@ant-design/icons-vue/CaretDownFilled';
|
import CaretDownFilled from '@ant-design/icons-vue/CaretDownFilled';
|
||||||
import type { AntTreeNodeProps } from '../Tree';
|
import type { AntTreeNodeProps } from '../Tree';
|
||||||
import { isValidElement } from 'ant-design-vue/es/_util/props-util';
|
import { isValidElement } from '../../_util/props-util';
|
||||||
|
|
||||||
import { cloneVNode } from 'vue';
|
import { cloneVNode } from 'vue';
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import type { VNodeChild } from 'vue';
|
||||||
import { Fragment } from 'vue';
|
import { Fragment } from 'vue';
|
||||||
import { computed, defineComponent, ref, watch } from 'vue';
|
import { computed, defineComponent, ref, watch } from 'vue';
|
||||||
import PropTypes from '../../_util/vue-types';
|
import PropTypes from '../../_util/vue-types';
|
||||||
import { useInjectTreeSelectContext } from 'ant-design-vue/es/vc-tree-select/Context';
|
import { useInjectTreeSelectContext } from '../../vc-tree-select/Context';
|
||||||
|
|
||||||
interface SelectorProps extends InnerSelectorProps {
|
interface SelectorProps extends InnerSelectorProps {
|
||||||
inputElement: VNodeChild;
|
inputElement: VNodeChild;
|
||||||
|
|
|
@ -1034,7 +1034,7 @@ export default function generateSelector<
|
||||||
internalProps = {},
|
internalProps = {},
|
||||||
|
|
||||||
...restProps
|
...restProps
|
||||||
} = props; //as SelectProps<OptionType[], ValueType>;
|
} = { ...props, ...attrs }; //as SelectProps<OptionType[], ValueType>;
|
||||||
// ============================= Input ==============================
|
// ============================= Input ==============================
|
||||||
// Only works in `combobox`
|
// Only works in `combobox`
|
||||||
const customizeInputElement: VNodeChild | JSX.Element =
|
const customizeInputElement: VNodeChild | JSX.Element =
|
||||||
|
@ -1144,9 +1144,8 @@ export default function generateSelector<
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
{...attrs}
|
|
||||||
class={mergedClassName}
|
|
||||||
{...domProps}
|
{...domProps}
|
||||||
|
class={mergedClassName}
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
onMousedown={onInternalMouseDown}
|
onMousedown={onInternalMouseDown}
|
||||||
onKeydown={onInternalKeyDown}
|
onKeydown={onInternalKeyDown}
|
||||||
|
|
|
@ -143,7 +143,7 @@ export default defineComponent({
|
||||||
activeKey.value = key;
|
activeKey.value = key;
|
||||||
};
|
};
|
||||||
expose({
|
expose({
|
||||||
scrollTo: (...args: any[]) => treeRef.value.scrollTo?.(...args),
|
scrollTo: (...args: any[]) => treeRef.value?.scrollTo?.(...args),
|
||||||
onKeydown: (event: KeyboardEvent) => {
|
onKeydown: (event: KeyboardEvent) => {
|
||||||
const { which } = event;
|
const { which } = event;
|
||||||
switch (which) {
|
switch (which) {
|
||||||
|
|
|
@ -64,6 +64,7 @@ const OMIT_PROPS: (keyof TreeSelectProps)[] = [
|
||||||
'treeDataSimpleMode',
|
'treeDataSimpleMode',
|
||||||
'treeNodeLabelProp',
|
'treeNodeLabelProp',
|
||||||
'treeDefaultExpandedKeys',
|
'treeDefaultExpandedKeys',
|
||||||
|
'bordered',
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function generate(config: {
|
export default function generate(config: {
|
||||||
|
@ -236,8 +237,9 @@ export default function generate(config: {
|
||||||
...checkedKeys.map(key => getEntityByKey(key).data.value),
|
...checkedKeys.map(key => getEntityByKey(key).data.value),
|
||||||
];
|
];
|
||||||
rawHalfCheckedKeys.value = halfCheckedKeys;
|
rawHalfCheckedKeys.value = halfCheckedKeys;
|
||||||
|
} else {
|
||||||
|
[rawValues.value, rawHalfCheckedKeys.value] = [newRawValues, valueHalfCheckedKeys];
|
||||||
}
|
}
|
||||||
[rawValues.value, rawHalfCheckedKeys.value] = [newRawValues, valueHalfCheckedKeys];
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const selectValues = useSelectValues(rawValues, {
|
const selectValues = useSelectValues(rawValues, {
|
||||||
|
@ -378,7 +380,7 @@ export default function generate(config: {
|
||||||
option: DataNode,
|
option: DataNode,
|
||||||
source: SelectSource,
|
source: SelectSource,
|
||||||
) => {
|
) => {
|
||||||
const eventValue = mergedLabelInValue.value ? selectValue : selectValue;
|
const eventValue = selectValue;
|
||||||
|
|
||||||
let newRawValues = removeValue(rawValues.value, selectValue);
|
let newRawValues = removeValue(rawValues.value, selectValue);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { warning } from 'ant-design-vue/es/vc-util/warning';
|
import { warning } from '../../vc-util/warning';
|
||||||
import type { ComputedRef, Ref } from 'vue';
|
import type { ComputedRef, Ref } from 'vue';
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import type {
|
import type {
|
||||||
|
@ -76,6 +76,7 @@ function formatTreeData(
|
||||||
value: mergedValue,
|
value: mergedValue,
|
||||||
title: getLabelProp(node),
|
title: getLabelProp(node),
|
||||||
node,
|
node,
|
||||||
|
dataRef: node,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (node.slots) {
|
if (node.slots) {
|
||||||
|
|
|
@ -39,6 +39,8 @@ export interface InternalDataEntity {
|
||||||
/** Origin DataNode */
|
/** Origin DataNode */
|
||||||
node: DataNode;
|
node: DataNode;
|
||||||
|
|
||||||
|
dataRef: DataNode;
|
||||||
|
|
||||||
slots?: Record<string, string>; // 兼容 V2
|
slots?: Record<string, string>; // 兼容 V2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,9 @@ import type {
|
||||||
} from '../interface';
|
} from '../interface';
|
||||||
import { fillLegacyProps } from './legacyUtil';
|
import { fillLegacyProps } from './legacyUtil';
|
||||||
import type { SkipType } from '../hooks/useKeyValueMapping';
|
import type { SkipType } from '../hooks/useKeyValueMapping';
|
||||||
import type { FlattenNode } from 'ant-design-vue/es/vc-tree/interface';
|
import type { FlattenNode } from '../../vc-tree/interface';
|
||||||
import { flattenTreeData } from 'ant-design-vue/es/vc-tree/utils/treeUtil';
|
import { flattenTreeData } from '../../vc-tree/utils/treeUtil';
|
||||||
import type { FilterFunc } from 'ant-design-vue/es/vc-select/interface/generator';
|
import type { FilterFunc } from '../../vc-select/interface/generator';
|
||||||
|
|
||||||
type CompatibleDataNode = Omit<FlattenDataNode, 'level'>;
|
type CompatibleDataNode = Omit<FlattenDataNode, 'level'>;
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
import { warning } from '../../vc-util/warning';
|
import { warning } from '../../vc-util/warning';
|
||||||
import type { TreeSelectProps } from '../TreeSelect';
|
|
||||||
import { toArray } from './valueUtil';
|
import { toArray } from './valueUtil';
|
||||||
|
|
||||||
function warningProps(props: TreeSelectProps) {
|
function warningProps(props: any) {
|
||||||
const { searchPlaceholder, treeCheckStrictly, treeCheckable, labelInValue, value, multiple } =
|
const { searchPlaceholder, treeCheckStrictly, treeCheckable, labelInValue, value, multiple } =
|
||||||
props;
|
props;
|
||||||
|
|
||||||
warning(!searchPlaceholder, '`searchPlaceholder` has been removed.');
|
warning(
|
||||||
|
!searchPlaceholder,
|
||||||
|
'`searchPlaceholder` has been removed, please use `placeholder` instead',
|
||||||
|
);
|
||||||
|
|
||||||
if (treeCheckStrictly && labelInValue === false) {
|
if (treeCheckStrictly && labelInValue === false) {
|
||||||
warning(false, '`treeCheckStrictly` will force set `labelInValue` to `true`.');
|
warning(false, '`treeCheckStrictly` will force set `labelInValue` to `true`.');
|
||||||
|
|
|
@ -634,7 +634,7 @@ export default defineComponent({
|
||||||
|
|
||||||
checkedObj = newCheckedKeys;
|
checkedObj = newCheckedKeys;
|
||||||
|
|
||||||
// [Legacy] This is used for `rc-tree-select`
|
// [Legacy] This is used for vc-tree-select`
|
||||||
eventObj.checkedNodes = [];
|
eventObj.checkedNodes = [];
|
||||||
eventObj.checkedNodesPositions = [];
|
eventObj.checkedNodesPositions = [];
|
||||||
eventObj.halfCheckedKeys = newHalfCheckedKeys;
|
eventObj.halfCheckedKeys = newHalfCheckedKeys;
|
||||||
|
@ -997,7 +997,6 @@ export default defineComponent({
|
||||||
|
|
||||||
const { class: className, style } = attrs;
|
const { class: className, style } = attrs;
|
||||||
const domProps = getDataAndAria({ ...props, ...attrs });
|
const domProps = getDataAndAria({ ...props, ...attrs });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TreeContext
|
<TreeContext
|
||||||
value={{
|
value={{
|
||||||
|
|
|
@ -402,8 +402,8 @@ export function convertNodePropsToEventData(props: TreeNodeProps): EventDataNode
|
||||||
pos,
|
pos,
|
||||||
active,
|
active,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const eventData = {
|
const eventData = {
|
||||||
|
dataRef: data,
|
||||||
...data,
|
...data,
|
||||||
expanded,
|
expanded,
|
||||||
selected,
|
selected,
|
||||||
|
@ -416,7 +416,6 @@ export function convertNodePropsToEventData(props: TreeNodeProps): EventDataNode
|
||||||
dragOverGapBottom,
|
dragOverGapBottom,
|
||||||
pos,
|
pos,
|
||||||
active,
|
active,
|
||||||
dataRef: data,
|
|
||||||
eventKey: data.key,
|
eventKey: data.key,
|
||||||
};
|
};
|
||||||
if (!('props' in eventData)) {
|
if (!('props' in eventData)) {
|
||||||
|
|
|
@ -1,40 +1,80 @@
|
||||||
<template>
|
<template>
|
||||||
<a-tree-select
|
<a-space direction="vertical" style="width: 100%">
|
||||||
v-model:value="value"
|
<a-tree-select
|
||||||
show-search
|
v-model:value="value"
|
||||||
style="width: 100%"
|
show-search
|
||||||
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
style="width: 100%"
|
||||||
placeholder="Please select"
|
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||||
allow-clear
|
placeholder="Please select"
|
||||||
multiple
|
allow-clear
|
||||||
tree-default-expand-all
|
tree-default-expand-all
|
||||||
>
|
:tree-data="treeData"
|
||||||
<a-tree-select-node value="parent 1" title="parent 1">
|
>
|
||||||
<a-tree-select-node value="parent 1-0" title="parent 1-0">
|
<template #suffixIcon><SmileOutlined /></template>
|
||||||
<a-tree-select-node value="leaf1" title="my leaf" />
|
</a-tree-select>
|
||||||
<a-tree-select-node value="leaf2" title="your leaf" />
|
|
||||||
</a-tree-select-node>
|
<a-tree-select
|
||||||
<a-tree-select-node value="parent 1-1" title="parent 1-1">
|
v-model:value="value1"
|
||||||
<a-tree-select-node value="sss">
|
show-search
|
||||||
<template #title><b style="color: #08c">sss</b></template>
|
style="width: 100%"
|
||||||
</a-tree-select-node>
|
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||||
</a-tree-select-node>
|
placeholder="Please select"
|
||||||
</a-tree-select-node>
|
allow-clear
|
||||||
</a-tree-select>
|
multiple
|
||||||
|
show-arrow
|
||||||
|
tree-default-expand-all
|
||||||
|
:tree-data="treeData"
|
||||||
|
>
|
||||||
|
<template #suffixIcon><SmileOutlined /></template>
|
||||||
|
</a-tree-select>
|
||||||
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { SmileOutlined } from '@ant-design/icons-vue';
|
||||||
|
import { TreeSelectProps } from 'ant-design-vue';
|
||||||
import { defineComponent, ref, watch } from 'vue';
|
import { defineComponent, ref, watch } from 'vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
SmileOutlined,
|
||||||
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const value = ref<string[]>([]);
|
const value = ref<string[]>([]);
|
||||||
|
const value1 = ref<string[]>([]);
|
||||||
|
const treeData = ref<TreeSelectProps['treeData']>([
|
||||||
|
{
|
||||||
|
title: 'parent 1',
|
||||||
|
value: 'parent 1',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: 'parent 1-0',
|
||||||
|
value: 'parent 1-0',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: 'my leaf',
|
||||||
|
value: 'leaf1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'your leaf',
|
||||||
|
value: 'leaf2',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'parent 1-1',
|
||||||
|
value: 'parent 1-1',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
watch(value, () => {
|
watch(value, () => {
|
||||||
console.log('select', value.value);
|
console.log('select', value.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
value,
|
value,
|
||||||
|
value1,
|
||||||
|
treeData,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
2
v2-doc
2
v2-doc
|
@ -1 +1 @@
|
||||||
Subproject commit 2e39bc81a84e2cfa90e8863e8f18d5a3d3ab1995
|
Subproject commit 3f94a02d16bac2377d71e26948ffe45571dae49e
|
Loading…
Reference in New Issue