ant-design-vue/components/tree-select/index.tsx

219 lines
7.0 KiB
Vue
Raw Normal View History

2021-06-26 01:35:40 +00:00
import type { App, Plugin } from 'vue';
import { defineComponent, inject } from 'vue';
2019-01-12 03:33:27 +00:00
import VcTreeSelect, { TreeNode, SHOW_ALL, SHOW_PARENT, SHOW_CHILD } from '../vc-tree-select';
2020-08-31 08:53:19 +00:00
import classNames from '../_util/classNames';
2019-01-12 03:33:27 +00:00
import { TreeSelectProps } from './interface';
import warning from '../_util/warning';
2020-10-22 02:06:57 +00:00
import { getOptionProps, getComponent, getSlot } from '../_util/props-util';
import initDefaultProps from '../_util/props-util/initDefaultProps';
import { defaultConfigProvider } from '../config-provider';
2018-07-11 09:51:20 +00:00
2019-01-12 03:33:27 +00:00
export { TreeData, TreeSelectProps } from './interface';
2020-03-28 07:47:48 +00:00
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
import CaretDownOutlined from '@ant-design/icons-vue/CaretDownOutlined';
import DownOutlined from '@ant-design/icons-vue/DownOutlined';
import CloseOutlined from '@ant-design/icons-vue/CloseOutlined';
2020-10-22 03:35:05 +00:00
import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled';
2019-01-12 03:33:27 +00:00
import omit from 'omit.js';
2020-10-22 03:35:05 +00:00
import { convertChildrenToData } from './utils';
2020-09-02 04:54:24 +00:00
2020-10-22 02:06:57 +00:00
const TreeSelect = defineComponent({
2020-09-02 04:54:24 +00:00
TreeNode,
2018-07-11 09:51:20 +00:00
SHOW_ALL,
SHOW_PARENT,
SHOW_CHILD,
name: 'ATreeSelect',
2020-11-07 07:37:17 +00:00
inheritAttrs: false,
2018-07-11 09:51:20 +00:00
props: initDefaultProps(TreeSelectProps(), {
transitionName: 'slide-up',
choiceTransitionName: '',
2018-07-11 09:51:20 +00:00
}),
2020-07-18 13:40:26 +00:00
setup() {
return {
2020-10-22 02:06:57 +00:00
vcTreeSelect: null,
configProvider: inject('configProvider', defaultConfigProvider),
2020-07-18 13:40:26 +00:00
};
2019-01-07 12:59:02 +00:00
},
2019-01-12 03:33:27 +00:00
created() {
2018-07-11 09:51:20 +00:00
warning(
this.multiple !== false || !this.treeCheckable,
Feat 1.5.0 (#1853) * feat: add Result component * fix: update md template tag html>tpl - fix `result` typo - update jest `result` snapshots * refactor: svg file to functional component icon - update jest snapshot * feat: add result * Feat descriptions (#1251) * feat: add descriptions * fix: add descriptions types and fix docs * fix: lint change code * fix: demo warning * fix: update demo, snapshot and remove classnames * test: add descriptions test * fix: descriptions demo (#1498) * feat: add page header (#1250) * feat: add page-header component * update site: page-header * ts definition update: page-header * get page-header props with getComponentFromProp func * optimize page-header * doc: add page-header actions.md responsive.md * breadcrumb itemRender add pure function support * style: format code * feat: update style to 3.23.6 from 2.13.6 * feat: update style to 3.26.8 from 3.23.6 * chore: update util * chore: update util * feat: update affix * feat: update alert * feat: update anchor * feat: update auto-complete * feat: update avatar * feat: update back-top * feat: update badge * feat: update button * feat: update breadcrumb * feat: update ts * docs: update doc * feat: update calendat * feat: update card * feat: update carousel * feat: update carousel * feat: update checkbox * feat: update comment * feat: update config-provider * docs: update doc * feat: update collapse * feat: update locale * feat: update date-picker * feat: update divider * feat: update drawer * feat: update dropdown * feat: update rc-trigger * feat: update dropdown * feat: update empty * test: add empty test * feat: update form * feat: update form * feat: update spin * feat: update grid * docs: update grid doc * feat: update icon * feat: update slider * feat: update textarea * feat: update input-number * feat: update layout * feat: update list * feat: update menu * feat: meaage add key for update content * feat: modal add closeIcon support * feat: update notification * feat: add pagination disabled support * feat: popconfirm add disabled support * test: update popover * feat: progress support custom line-gradiend * feat: update radio * test: update radio test * docs: update rate demo * feat: skeleton add avatar support number type * test: add switch test * test: update statistic test * fix: input clear icon event * feat: steps add type、 v-model、subTitle * feat: delete typography component * feat: delete Typography style * perf: update select * feat: add download transformFile previewFile actio * docs: update upload * feat: update tree-select * docs: update tree-select * feat: tree add blockNode selectable * docs: add tree demo * test: update snap * docs: updatedoc * feat: update tag * docs: update ad doc * feat: update tooltip * feat: update timeline * feat: time-picker add clearIcon * docs: update tabs * feat: transfer support custom children * test: update transfer test * feat: update table * test: update table test * test: update test * feat: calendar update locale * test: update test snap * feat: add mentions (#1790) * feat: mentions style * feat: theme default * feat: add mentions component * feat: mentions API * feat: add unit test for mentions * feat: update mentions demo * perf: model and inheritAttrs for mentions * perf: use getComponentFromProp instead of this.$props * perf: mentions rm defaultProps * feat: rm rows in mentionsProps * fix: mentions keyDown didn't work * docs: update mentions api * perf: mentions code * feat: update mentions * bump 1.5.0-alpha.1 * feat: pageheader add ghost prop * docs: update descriptions demo * chore: page-header add ghost type * fix: color error * feat: update to 3.26.12 * fix: some prop default value * fix(typo): form, carousel, upload. duplicate identifier (#1848) * Add Mentions Type (#1845) * feat: add mentions type * feat: add mentions in ant-design-vue.d.ts * docs: update doc * docs: add changelog * fix: mentions getPopupCotainer value (#1850) * docs: update doc * docs: uptate demo * docs: update demo * docs: delete demo * docs: delete doc * test: update snapshots * style: format code * chore: update travis * docs: update demo Co-authored-by: Sendya <18x@loacg.com> Co-authored-by: zkwolf <chenhao5866@gmail.com> Co-authored-by: drafish <xwlyy1991@163.com> Co-authored-by: Amour1688 <31695475+Amour1688@users.noreply.github.com>
2020-03-07 11:45:13 +00:00
'TreeSelect',
2018-07-11 09:51:20 +00:00
'`multiple` will alway be `true` when `treeCheckable` is true',
2019-01-12 03:33:27 +00:00
);
2018-07-11 09:51:20 +00:00
},
methods: {
2020-10-22 03:35:05 +00:00
saveTreeSelect(node: any) {
2020-07-18 13:40:26 +00:00
this.vcTreeSelect = node;
},
2019-01-12 03:33:27 +00:00
focus() {
2020-07-18 13:40:26 +00:00
this.vcTreeSelect.focus();
2018-07-11 09:51:20 +00:00
},
2019-01-12 03:33:27 +00:00
blur() {
2020-07-18 13:40:26 +00:00
this.vcTreeSelect.blur();
2018-07-11 09:51:20 +00:00
},
2020-10-22 03:35:05 +00:00
renderSwitcherIcon(prefixCls: string, { isLeaf, loading }) {
2018-12-12 13:24:12 +00:00
if (loading) {
2020-03-28 07:47:48 +00:00
return <LoadingOutlined class={`${prefixCls}-switcher-loading-icon`} />;
2018-12-12 13:24:12 +00:00
}
if (isLeaf) {
2019-01-12 03:33:27 +00:00
return null;
2018-12-12 13:24:12 +00:00
}
2020-03-28 07:47:48 +00:00
return <CaretDownOutlined class={`${prefixCls}-switcher-icon`} />;
2018-12-12 13:24:12 +00:00
},
2020-10-22 03:35:05 +00:00
handleChange(...args: any[]) {
2020-07-18 13:40:26 +00:00
this.$emit('update:value', args[0]);
this.$emit('change', ...args);
2018-07-11 09:51:20 +00:00
},
2020-10-22 03:35:05 +00:00
handleTreeExpand(...args: any[]) {
2020-08-12 13:35:45 +00:00
this.$emit('update:treeExpandedKeys', args[0]);
this.$emit('treeExpand', ...args);
},
2020-10-22 03:35:05 +00:00
handleSearch(...args: any[]) {
2020-08-12 13:35:45 +00:00
this.$emit('update:searchValue', args[0]);
this.$emit('search', ...args);
},
2020-10-22 03:35:05 +00:00
updateTreeData(treeData: any[]) {
2020-07-18 13:40:26 +00:00
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 => {
2020-07-18 13:40:26 +00:00
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];
2020-07-18 13:40:26 +00:00
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)}</>;
2018-07-11 09:51:20 +00:00
}
2020-07-18 13:40:26 +00:00
if (!newTitle && slots.title && $slots[slots.title]) {
newTitle = <>{$slots[slots.title](item)}</>;
2018-07-11 09:51:20 +00:00
}
const treeNodeProps = {
...item,
2018-07-11 09:51:20 +00:00
title: newTitle || newLabel,
value,
dataRef: item,
key,
2019-01-12 03:33:27 +00:00
};
if (children) {
return { ...treeNodeProps, children: this.updateTreeData(children) };
}
return treeNodeProps;
});
2018-07-11 09:51:20 +00:00
},
2019-04-10 03:54:42 +00:00
},
2018-12-12 13:24:12 +00:00
2020-07-18 13:40:26 +00:00
render() {
2020-10-22 02:06:57 +00:00
const props: any = getOptionProps(this);
2019-05-28 03:37:38 +00:00
const {
prefixCls: customizePrefixCls,
size,
dropdownStyle,
dropdownClassName,
getPopupContainer,
...restProps
} = props;
2020-07-18 13:40:26 +00:00
const { class: className } = this.$attrs;
2020-10-22 02:06:57 +00:00
const { renderEmpty, getPrefixCls } = this.configProvider;
2019-05-28 03:37:38 +00:00
const prefixCls = getPrefixCls('select', customizePrefixCls);
2019-04-10 03:54:42 +00:00
2020-07-18 13:40:26 +00:00
const notFoundContent = getComponent(this, 'notFoundContent');
const removeIcon = getComponent(this, 'removeIcon');
const clearIcon = getComponent(this, 'clearIcon');
2019-05-28 03:37:38 +00:00
const { getPopupContainer: getContextPopupContainer } = this.configProvider;
const rest = omit(restProps, [
'inputIcon',
'removeIcon',
'clearIcon',
'switcherIcon',
'suffixIcon',
]);
2020-07-18 13:40:26 +00:00
let suffixIcon = getComponent(this, 'suffixIcon');
2019-05-28 03:37:38 +00:00
suffixIcon = Array.isArray(suffixIcon) ? suffixIcon[0] : suffixIcon;
let treeData = props.treeData;
if (treeData) {
treeData = this.updateTreeData(treeData);
}
const cls = {
[`${prefixCls}-lg`]: size === 'large',
[`${prefixCls}-sm`]: size === 'small',
2020-10-22 02:06:57 +00:00
[className as string]: className,
2019-05-28 03:37:38 +00:00
};
2018-07-11 09:51:20 +00:00
Feat 1.5.0 (#1853) * feat: add Result component * fix: update md template tag html>tpl - fix `result` typo - update jest `result` snapshots * refactor: svg file to functional component icon - update jest snapshot * feat: add result * Feat descriptions (#1251) * feat: add descriptions * fix: add descriptions types and fix docs * fix: lint change code * fix: demo warning * fix: update demo, snapshot and remove classnames * test: add descriptions test * fix: descriptions demo (#1498) * feat: add page header (#1250) * feat: add page-header component * update site: page-header * ts definition update: page-header * get page-header props with getComponentFromProp func * optimize page-header * doc: add page-header actions.md responsive.md * breadcrumb itemRender add pure function support * style: format code * feat: update style to 3.23.6 from 2.13.6 * feat: update style to 3.26.8 from 3.23.6 * chore: update util * chore: update util * feat: update affix * feat: update alert * feat: update anchor * feat: update auto-complete * feat: update avatar * feat: update back-top * feat: update badge * feat: update button * feat: update breadcrumb * feat: update ts * docs: update doc * feat: update calendat * feat: update card * feat: update carousel * feat: update carousel * feat: update checkbox * feat: update comment * feat: update config-provider * docs: update doc * feat: update collapse * feat: update locale * feat: update date-picker * feat: update divider * feat: update drawer * feat: update dropdown * feat: update rc-trigger * feat: update dropdown * feat: update empty * test: add empty test * feat: update form * feat: update form * feat: update spin * feat: update grid * docs: update grid doc * feat: update icon * feat: update slider * feat: update textarea * feat: update input-number * feat: update layout * feat: update list * feat: update menu * feat: meaage add key for update content * feat: modal add closeIcon support * feat: update notification * feat: add pagination disabled support * feat: popconfirm add disabled support * test: update popover * feat: progress support custom line-gradiend * feat: update radio * test: update radio test * docs: update rate demo * feat: skeleton add avatar support number type * test: add switch test * test: update statistic test * fix: input clear icon event * feat: steps add type、 v-model、subTitle * feat: delete typography component * feat: delete Typography style * perf: update select * feat: add download transformFile previewFile actio * docs: update upload * feat: update tree-select * docs: update tree-select * feat: tree add blockNode selectable * docs: add tree demo * test: update snap * docs: updatedoc * feat: update tag * docs: update ad doc * feat: update tooltip * feat: update timeline * feat: time-picker add clearIcon * docs: update tabs * feat: transfer support custom children * test: update transfer test * feat: update table * test: update table test * test: update test * feat: calendar update locale * test: update test snap * feat: add mentions (#1790) * feat: mentions style * feat: theme default * feat: add mentions component * feat: mentions API * feat: add unit test for mentions * feat: update mentions demo * perf: model and inheritAttrs for mentions * perf: use getComponentFromProp instead of this.$props * perf: mentions rm defaultProps * feat: rm rows in mentionsProps * fix: mentions keyDown didn't work * docs: update mentions api * perf: mentions code * feat: update mentions * bump 1.5.0-alpha.1 * feat: pageheader add ghost prop * docs: update descriptions demo * chore: page-header add ghost type * fix: color error * feat: update to 3.26.12 * fix: some prop default value * fix(typo): form, carousel, upload. duplicate identifier (#1848) * Add Mentions Type (#1845) * feat: add mentions type * feat: add mentions in ant-design-vue.d.ts * docs: update doc * docs: add changelog * fix: mentions getPopupCotainer value (#1850) * docs: update doc * docs: uptate demo * docs: update demo * docs: delete demo * docs: delete doc * test: update snapshots * style: format code * chore: update travis * docs: update demo Co-authored-by: Sendya <18x@loacg.com> Co-authored-by: zkwolf <chenhao5866@gmail.com> Co-authored-by: drafish <xwlyy1991@163.com> Co-authored-by: Amour1688 <31695475+Amour1688@users.noreply.github.com>
2020-03-07 11:45:13 +00:00
// showSearch: single - false, multiple - true
let { showSearch } = restProps;
if (!('showSearch' in restProps)) {
showSearch = !!(restProps.multiple || restProps.treeCheckable);
}
2020-07-18 13:40:26 +00:00
let checkable = getComponent(this, 'treeCheckable');
2019-05-28 03:37:38 +00:00
if (checkable) {
checkable = <span class={`${prefixCls}-tree-checkbox-inner`} />;
}
2018-12-12 13:24:12 +00:00
2020-03-28 07:47:48 +00:00
const inputIcon = suffixIcon || <DownOutlined class={`${prefixCls}-arrow-icon`} />;
2018-12-12 13:24:12 +00:00
2020-03-28 07:47:48 +00:00
const finalRemoveIcon = removeIcon || <CloseOutlined class={`${prefixCls}-remove-icon`} />;
2018-12-12 13:24:12 +00:00
2020-10-22 03:35:05 +00:00
const finalClearIcon = clearIcon || <CloseCircleFilled class={`${prefixCls}-clear-icon`} />;
2019-05-28 03:37:38 +00:00
const VcTreeSelectProps = {
2020-07-18 13:40:26 +00:00
...this.$attrs,
2020-08-12 13:35:45 +00:00
switcherIcon: nodeProps => this.renderSwitcherIcon(prefixCls, nodeProps),
inputIcon,
removeIcon: finalRemoveIcon,
clearIcon: finalClearIcon,
...rest,
showSearch,
getPopupContainer: getPopupContainer || getContextPopupContainer,
dropdownClassName: classNames(dropdownClassName, `${prefixCls}-tree-dropdown`),
prefixCls,
dropdownStyle: { maxHeight: '100vh', overflow: 'auto', ...dropdownStyle },
treeCheckable: checkable,
notFoundContent: notFoundContent || renderEmpty('Select'),
2019-05-28 03:37:38 +00:00
class: cls,
2020-08-12 13:35:45 +00:00
onChange: this.handleChange,
onSearch: this.handleSearch,
onTreeExpand: this.handleTreeExpand,
2020-07-18 13:40:26 +00:00
ref: this.saveTreeSelect,
2020-10-22 03:35:05 +00:00
treeData: treeData ? treeData : convertChildrenToData(getSlot(this)),
2019-05-28 03:37:38 +00:00
};
2020-08-12 08:30:13 +00:00
return (
<VcTreeSelect
{...VcTreeSelectProps}
2020-11-24 10:07:45 +00:00
v-slots={omit(this.$slots, ['default'])}
2020-08-27 10:34:23 +00:00
__propsSymbol__={[]}
2020-08-12 08:30:13 +00:00
/>
);
2018-07-11 09:51:20 +00:00
},
2020-10-22 02:06:57 +00:00
});
/* istanbul ignore next */
2021-06-23 15:08:16 +00:00
TreeSelect.install = function (app: App) {
2020-07-18 13:40:26 +00:00
app.component(TreeSelect.name, TreeSelect);
app.component(TreeSelect.TreeNode.displayName, TreeSelect.TreeNode);
2020-10-13 11:14:56 +00:00
return app;
2019-01-12 03:33:27 +00:00
};
2021-06-23 13:47:53 +00:00
export const TreeSelectNode = TreeSelect.TreeNode;
2020-11-01 07:03:33 +00:00
export default TreeSelect as typeof TreeSelect &
Plugin & {
readonly TreeNode: typeof TreeNode;
2020-10-22 03:35:05 +00:00
2020-11-01 07:03:33 +00:00
readonly SHOW_ALL: typeof SHOW_ALL;
2020-10-22 03:35:05 +00:00
2020-11-01 07:03:33 +00:00
readonly SHOW_PARENT: typeof SHOW_PARENT;
2020-10-22 03:35:05 +00:00
2020-11-01 07:03:33 +00:00
readonly SHOW_CHILD: typeof SHOW_CHILD;
};