mirror of
https://gitee.com/ant-design-vue/ant-design-vue.git
synced 2024-12-02 03:58:05 +08:00
feat: tree-select
This commit is contained in:
parent
b442cc0553
commit
61b5bfa0f6
@ -1 +1 @@
|
||||
Subproject commit 1cf8913c4b662bc2bda8ec44734e445ec370cc60
|
||||
Subproject commit e142c7f8cb2025c14d973691cfb90603e9790d46
|
@ -93,3 +93,7 @@ v-model -> v-model:activeKey
|
||||
## List
|
||||
|
||||
renderItem(item, index) => renderItem({item, index}) 该用单参数
|
||||
|
||||
## TreeSelect
|
||||
|
||||
treeData 中 scopedSlots => slots , v-model => v-model:value
|
||||
|
@ -112,17 +112,8 @@ const getAllChildren = ele => {
|
||||
}
|
||||
return ele.children || componentOptions.children || [];
|
||||
};
|
||||
const getSlotOptions = ele => {
|
||||
const getSlotOptions = () => {
|
||||
throw Error('使用 .type 直接取值');
|
||||
if (ele.fnOptions) {
|
||||
// 函数式组件
|
||||
return ele.fnOptions;
|
||||
}
|
||||
let componentOptions = ele.componentOptions;
|
||||
if (ele.$vnode) {
|
||||
componentOptions = ele.$vnode.componentOptions;
|
||||
}
|
||||
return componentOptions ? componentOptions.Ctor.options || {} : {};
|
||||
};
|
||||
const findDOMNode = instance => {
|
||||
let node = instance.$el || instance;
|
||||
@ -148,7 +139,7 @@ const getOptionProps = instance => {
|
||||
Object.keys(originProps).forEach(key => {
|
||||
props[camelize(key)] = originProps[key];
|
||||
});
|
||||
const options = instance.type.props;
|
||||
const options = instance.type.props || {};
|
||||
Object.keys(options).forEach(k => {
|
||||
const v = resolvePropValue(options, props, k, props[k]);
|
||||
if (v !== undefined || k in props) {
|
||||
@ -246,13 +237,14 @@ const getPropsData = ins => {
|
||||
props[camelize(key)] = originProps[key];
|
||||
});
|
||||
const options = isPlainObject(vnode.type) ? vnode.type.props : {};
|
||||
Object.keys(options).forEach(k => {
|
||||
const v = resolvePropValue(options, props, k, props[k]);
|
||||
if (k in props) {
|
||||
// 仅包含 props,不包含默认值
|
||||
res[k] = v;
|
||||
}
|
||||
});
|
||||
options &&
|
||||
Object.keys(options).forEach(k => {
|
||||
const v = resolvePropValue(options, props, k, props[k]);
|
||||
if (k in props) {
|
||||
// 仅包含 props,不包含默认值
|
||||
res[k] = v;
|
||||
}
|
||||
});
|
||||
return { ...props, ...res }; // 合并事件、未声明属性等
|
||||
};
|
||||
const getValueByProp = (ele, prop) => {
|
||||
|
@ -302,7 +302,6 @@ const Cascader = {
|
||||
},
|
||||
|
||||
generateFilteredOptions(prefixCls, renderEmpty) {
|
||||
const h = this.$createElement;
|
||||
const { showSearch, notFoundContent } = this;
|
||||
const names = getFilledFieldNames(this.$props);
|
||||
const {
|
||||
@ -356,7 +355,7 @@ const Cascader = {
|
||||
}
|
||||
return [
|
||||
{
|
||||
[names.label]: notFoundContent || renderEmpty(h, 'Cascader'),
|
||||
[names.label]: notFoundContent || renderEmpty('Cascader'),
|
||||
[names.value]: 'ANT_CASCADER_NOT_FOUND',
|
||||
disabled: true,
|
||||
},
|
||||
@ -543,4 +542,8 @@ const Cascader = {
|
||||
},
|
||||
};
|
||||
|
||||
Cascader.install = function(app) {
|
||||
app.component(Cascader.name, Cascader);
|
||||
};
|
||||
|
||||
export default Cascader;
|
||||
|
@ -96,7 +96,6 @@ export default {
|
||||
return null;
|
||||
},
|
||||
renderIndicator(h, prefixCls) {
|
||||
// const h = this.$createElement
|
||||
const dotClassName = `${prefixCls}-dot`;
|
||||
let indicator = getComponent(this, 'indicator');
|
||||
// should not be render default indicator when indicator value is null
|
||||
|
@ -120,10 +120,9 @@ const Transfer = {
|
||||
},
|
||||
|
||||
getLocale(transferLocale, renderEmpty) {
|
||||
const h = this.$createElement;
|
||||
// Keep old locale props still working.
|
||||
const oldLocale = {
|
||||
notFoundContent: renderEmpty(h, 'Transfer'),
|
||||
notFoundContent: renderEmpty('Transfer'),
|
||||
};
|
||||
const notFoundContent = getComponentFromProp(this, 'notFoundContent');
|
||||
if (notFoundContent) {
|
||||
|
@ -174,7 +174,7 @@ export default {
|
||||
if (!listBody) {
|
||||
let bodyNode;
|
||||
|
||||
const { bodyContent, customize } = renderListNode(this.$createElement, renderList, {
|
||||
const { bodyContent, customize } = renderListNode(renderList, {
|
||||
props: { ...this.$props, filteredItems, filteredRenderItems, selectedKeys: checkedKeys },
|
||||
on: getListeners(this),
|
||||
});
|
||||
|
@ -1,16 +1,10 @@
|
||||
import VcTreeSelect, { TreeNode, SHOW_ALL, SHOW_PARENT, SHOW_CHILD } from '../vc-tree-select';
|
||||
import { inject } from 'vue';
|
||||
import classNames from 'classnames';
|
||||
import { TreeSelectProps } from './interface';
|
||||
import warning from '../_util/warning';
|
||||
import {
|
||||
initDefaultProps,
|
||||
getOptionProps,
|
||||
getComponentFromProp,
|
||||
filterEmpty,
|
||||
getListeners,
|
||||
} from '../_util/props-util';
|
||||
import { initDefaultProps, getOptionProps, getComponent, getSlot } from '../_util/props-util';
|
||||
import { ConfigConsumerProps } from '../config-provider';
|
||||
import Base from '../base';
|
||||
|
||||
export { TreeData, TreeSelectProps } from './interface';
|
||||
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
|
||||
@ -19,24 +13,26 @@ import DownOutlined from '@ant-design/icons-vue/DownOutlined';
|
||||
import CloseOutlined from '@ant-design/icons-vue/CloseOutlined';
|
||||
import CloseCircleOutlined from '@ant-design/icons-vue/CloseCircleOutlined';
|
||||
import omit from 'omit.js';
|
||||
|
||||
const ATreeSelectNode = function ATreeSelectNode(props, ctx) {
|
||||
return TreeNode(props, ctx);
|
||||
};
|
||||
Object.keys(TreeNode).forEach(key => (ATreeSelectNode[key] = TreeNode[key]));
|
||||
const TreeSelect = {
|
||||
TreeNode: { ...TreeNode, name: 'ATreeSelectNode' },
|
||||
TreeNode: ATreeSelectNode,
|
||||
SHOW_ALL,
|
||||
SHOW_PARENT,
|
||||
SHOW_CHILD,
|
||||
inheritAttrs: false,
|
||||
name: 'ATreeSelect',
|
||||
props: initDefaultProps(TreeSelectProps(), {
|
||||
transitionName: 'slide-up',
|
||||
choiceTransitionName: 'zoom',
|
||||
showSearch: false,
|
||||
}),
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'change',
|
||||
},
|
||||
inject: {
|
||||
configProvider: { default: () => ConfigConsumerProps },
|
||||
setup() {
|
||||
return {
|
||||
configProvider: inject('configProvider', ConfigConsumerProps),
|
||||
};
|
||||
},
|
||||
created() {
|
||||
warning(
|
||||
@ -46,12 +42,15 @@ const TreeSelect = {
|
||||
);
|
||||
},
|
||||
methods: {
|
||||
saveTreeSelect(node) {
|
||||
this.vcTreeSelect = node;
|
||||
},
|
||||
focus() {
|
||||
this.$refs.vcTreeSelect.focus();
|
||||
this.vcTreeSelect.focus();
|
||||
},
|
||||
|
||||
blur() {
|
||||
this.$refs.vcTreeSelect.blur();
|
||||
this.vcTreeSelect.blur();
|
||||
},
|
||||
renderSwitcherIcon(prefixCls, { isLeaf, loading }) {
|
||||
if (loading) {
|
||||
@ -62,11 +61,12 @@ const TreeSelect = {
|
||||
}
|
||||
return <CaretDownOutlined class={`${prefixCls}-switcher-icon`} />;
|
||||
},
|
||||
onChange() {
|
||||
this.$emit('change', ...arguments);
|
||||
onChange(...args) {
|
||||
this.$emit('update:value', args[0]);
|
||||
this.$emit('change', ...args);
|
||||
},
|
||||
updateTreeData(treeData) {
|
||||
const { $scopedSlots } = this;
|
||||
const { $slots } = this;
|
||||
const defaultFields = {
|
||||
children: 'children',
|
||||
title: 'title',
|
||||
@ -76,19 +76,19 @@ const TreeSelect = {
|
||||
};
|
||||
const replaceFields = { ...defaultFields, ...this.$props.replaceFields };
|
||||
return treeData.map(item => {
|
||||
const { scopedSlots = {} } = 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(this.$createElement) : label;
|
||||
let newTitle = typeof title === 'function' ? title(this.$createElement) : title;
|
||||
if (!newLabel && scopedSlots.label && $scopedSlots[scopedSlots.label]) {
|
||||
newLabel = $scopedSlots.label(item);
|
||||
let newLabel = typeof label === 'function' ? label() : label;
|
||||
let newTitle = typeof title === 'function' ? title() : title;
|
||||
if (!newLabel && slots.label && $slots[slots.label]) {
|
||||
newLabel = $slots.label(item);
|
||||
}
|
||||
if (!newTitle && scopedSlots.title && $scopedSlots[scopedSlots.title]) {
|
||||
newTitle = $scopedSlots.title(item);
|
||||
if (!newTitle && slots.title && $slots[slots.title]) {
|
||||
newTitle = $slots.title(item);
|
||||
}
|
||||
const treeNodeProps = {
|
||||
...item,
|
||||
@ -105,7 +105,7 @@ const TreeSelect = {
|
||||
},
|
||||
},
|
||||
|
||||
render(h) {
|
||||
render() {
|
||||
const props = getOptionProps(this);
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
@ -115,13 +115,14 @@ const TreeSelect = {
|
||||
getPopupContainer,
|
||||
...restProps
|
||||
} = props;
|
||||
const { class: className } = this.$attrs;
|
||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||
const prefixCls = getPrefixCls('select', customizePrefixCls);
|
||||
|
||||
const renderEmpty = this.configProvider.renderEmpty;
|
||||
const notFoundContent = getComponentFromProp(this, 'notFoundContent');
|
||||
const removeIcon = getComponentFromProp(this, 'removeIcon');
|
||||
const clearIcon = getComponentFromProp(this, 'clearIcon');
|
||||
const notFoundContent = getComponent(this, 'notFoundContent');
|
||||
const removeIcon = getComponent(this, 'removeIcon');
|
||||
const clearIcon = getComponent(this, 'clearIcon');
|
||||
const { getPopupContainer: getContextPopupContainer } = this.configProvider;
|
||||
const rest = omit(restProps, [
|
||||
'inputIcon',
|
||||
@ -130,7 +131,7 @@ const TreeSelect = {
|
||||
'switcherIcon',
|
||||
'suffixIcon',
|
||||
]);
|
||||
let suffixIcon = getComponentFromProp(this, 'suffixIcon');
|
||||
let suffixIcon = getComponent(this, 'suffixIcon');
|
||||
suffixIcon = Array.isArray(suffixIcon) ? suffixIcon[0] : suffixIcon;
|
||||
let treeData = props.treeData;
|
||||
if (treeData) {
|
||||
@ -139,6 +140,7 @@ const TreeSelect = {
|
||||
const cls = {
|
||||
[`${prefixCls}-lg`]: size === 'large',
|
||||
[`${prefixCls}-sm`]: size === 'small',
|
||||
[className]: className,
|
||||
};
|
||||
|
||||
// showSearch: single - false, multiple - true
|
||||
@ -147,7 +149,7 @@ const TreeSelect = {
|
||||
showSearch = !!(restProps.multiple || restProps.treeCheckable);
|
||||
}
|
||||
|
||||
let checkable = getComponentFromProp(this, 'treeCheckable');
|
||||
let checkable = getComponent(this, 'treeCheckable');
|
||||
if (checkable) {
|
||||
checkable = <span class={`${prefixCls}-tree-checkbox-inner`} />;
|
||||
}
|
||||
@ -160,7 +162,8 @@ const TreeSelect = {
|
||||
<CloseCircleOutlined class={`${prefixCls}-clear-icon`} theme="filled" />
|
||||
);
|
||||
const VcTreeSelectProps = {
|
||||
props: Object.assign(
|
||||
...this.$attrs,
|
||||
...Object.assign(
|
||||
{
|
||||
switcherIcon: nodeProps => this.renderSwitcherIcon(prefixCls, nodeProps),
|
||||
inputIcon,
|
||||
@ -173,25 +176,24 @@ const TreeSelect = {
|
||||
prefixCls,
|
||||
dropdownStyle: { maxHeight: '100vh', overflow: 'auto', ...dropdownStyle },
|
||||
treeCheckable: checkable,
|
||||
notFoundContent: notFoundContent || renderEmpty(h, 'Select'),
|
||||
notFoundContent: notFoundContent || renderEmpty('Select'),
|
||||
__propsSymbol__: Symbol(),
|
||||
},
|
||||
treeData ? { treeData } : {},
|
||||
),
|
||||
class: cls,
|
||||
on: { ...getListeners(this), change: this.onChange },
|
||||
ref: 'vcTreeSelect',
|
||||
scopedSlots: this.$scopedSlots,
|
||||
onChange: this.onChange,
|
||||
ref: this.saveTreeSelect,
|
||||
children: getSlot(this),
|
||||
};
|
||||
return <VcTreeSelect {...VcTreeSelectProps}>{filterEmpty(this.$slots.default)}</VcTreeSelect>;
|
||||
return <VcTreeSelect {...VcTreeSelectProps} vSlots={omit(this.$slots, ['default'])} />;
|
||||
},
|
||||
};
|
||||
|
||||
/* istanbul ignore next */
|
||||
TreeSelect.install = function(Vue) {
|
||||
Vue.use(Base);
|
||||
Vue.component(TreeSelect.name, TreeSelect);
|
||||
Vue.component(TreeSelect.TreeNode.name, TreeSelect.TreeNode);
|
||||
TreeSelect.install = function(app) {
|
||||
app.component(TreeSelect.name, TreeSelect);
|
||||
app.component(TreeSelect.TreeNode.name, TreeSelect.TreeNode);
|
||||
};
|
||||
|
||||
export default TreeSelect;
|
||||
|
@ -54,4 +54,6 @@ export const TreeSelectProps = () => ({
|
||||
treeNodeFilterProp: PropTypes.string,
|
||||
treeNodeLabelProp: PropTypes.string,
|
||||
replaceFields: PropTypes.object.def({}),
|
||||
clearIcon: PropTypes.any,
|
||||
removeIcon: PropTypes.any,
|
||||
});
|
||||
|
@ -1,10 +1,6 @@
|
||||
// export this package's api
|
||||
// base 2.9.3
|
||||
import Vue from 'vue';
|
||||
import TreeSelect from './src';
|
||||
import ref from 'vue-ref';
|
||||
|
||||
Vue.use(ref, { name: 'ant-ref' });
|
||||
export default TreeSelect;
|
||||
|
||||
export { TreeNode, SHOW_ALL, SHOW_PARENT, SHOW_CHILD } from './src';
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { inject } from 'vue';
|
||||
import warning from 'warning';
|
||||
import PropTypes from '../../../_util/vue-types';
|
||||
import { Tree } from '../../../vc-tree';
|
||||
@ -69,6 +70,7 @@ function getDerivedState(nextProps, prevState) {
|
||||
}
|
||||
const BasePopup = {
|
||||
mixins: [BaseMixin],
|
||||
inheritAttrs: false,
|
||||
name: 'BasePopup',
|
||||
props: {
|
||||
prefixCls: PropTypes.string,
|
||||
@ -101,8 +103,10 @@ const BasePopup = {
|
||||
|
||||
__propsSymbol__: PropTypes.any,
|
||||
},
|
||||
inject: {
|
||||
vcTreeSelect: { default: () => ({}) },
|
||||
setup() {
|
||||
return {
|
||||
vcTreeSelect: inject('vcTreeSelect', {}),
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
__propsSymbol__() {
|
||||
@ -248,37 +252,27 @@ const BasePopup = {
|
||||
$tree = $notFound;
|
||||
} else {
|
||||
const treeAllProps = {
|
||||
props: {
|
||||
prefixCls: `${prefixCls}-tree`,
|
||||
showIcon: treeIcon,
|
||||
showLine: treeLine,
|
||||
selectable: !treeCheckable,
|
||||
checkable: treeCheckable,
|
||||
checkStrictly: treeCheckStrictly,
|
||||
multiple,
|
||||
loadData,
|
||||
loadedKeys,
|
||||
expandedKeys: expandedKeyList,
|
||||
filterTreeNode: this.filterTreeNode,
|
||||
switcherIcon,
|
||||
...treeProps,
|
||||
__propsSymbol__: Symbol(),
|
||||
children: $treeNodes,
|
||||
},
|
||||
on: {
|
||||
select: onTreeNodeSelect,
|
||||
check: onTreeNodeCheck,
|
||||
expand: this.onTreeExpand,
|
||||
load: this.onLoad,
|
||||
},
|
||||
directives: [
|
||||
{
|
||||
name: 'ant-ref',
|
||||
value: this.treeRef,
|
||||
},
|
||||
],
|
||||
prefixCls: `${prefixCls}-tree`,
|
||||
showIcon: treeIcon,
|
||||
showLine: treeLine,
|
||||
selectable: !treeCheckable,
|
||||
checkable: treeCheckable,
|
||||
checkStrictly: treeCheckStrictly,
|
||||
multiple,
|
||||
loadData,
|
||||
loadedKeys,
|
||||
expandedKeys: expandedKeyList,
|
||||
filterTreeNode: this.filterTreeNode,
|
||||
switcherIcon,
|
||||
...treeProps,
|
||||
__propsSymbol__: Symbol(),
|
||||
children: $treeNodes,
|
||||
onSelect: onTreeNodeSelect,
|
||||
onCheck: onTreeNodeCheck,
|
||||
onExpand: this.onTreeExpand,
|
||||
onLoad: this.onLoad,
|
||||
};
|
||||
$tree = <Tree {...treeAllProps} />;
|
||||
$tree = <Tree {...treeAllProps} ref={this.treeRef} />;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -5,14 +5,14 @@
|
||||
*
|
||||
* So this file named as Selector to avoid confuse.
|
||||
*/
|
||||
import { inject } from 'vue';
|
||||
import { createRef } from '../util';
|
||||
import PropTypes from '../../../_util/vue-types';
|
||||
import classNames from 'classnames';
|
||||
import { initDefaultProps, getComponentFromProp, getListeners } from '../../../_util/props-util';
|
||||
import { initDefaultProps, getComponent } from '../../../_util/props-util';
|
||||
import BaseMixin from '../../../_util/BaseMixin';
|
||||
export const selectorPropTypes = () => ({
|
||||
prefixCls: PropTypes.string,
|
||||
className: PropTypes.string,
|
||||
open: PropTypes.bool,
|
||||
selectorValueList: PropTypes.array,
|
||||
allowClear: PropTypes.bool,
|
||||
@ -36,6 +36,7 @@ function noop() {}
|
||||
export default function(modeName) {
|
||||
const BaseSelector = {
|
||||
name: 'BaseSelector',
|
||||
inheritAttrs: false,
|
||||
mixins: [BaseMixin],
|
||||
props: initDefaultProps(
|
||||
{
|
||||
@ -50,8 +51,10 @@ export default function(modeName) {
|
||||
tabindex: 0,
|
||||
},
|
||||
),
|
||||
inject: {
|
||||
vcTreeSelect: { default: () => ({}) },
|
||||
setup() {
|
||||
return {
|
||||
vcTreeSelect: inject('vcTreeSelect', {}),
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.domRef = createRef();
|
||||
@ -96,7 +99,7 @@ export default function(modeName) {
|
||||
if (!allowClear || !selectorValueList.length || !selectorValueList[0].value) {
|
||||
return null;
|
||||
}
|
||||
const clearIcon = getComponentFromProp(this, 'clearIcon');
|
||||
const clearIcon = getComponent(this, 'clearIcon');
|
||||
return (
|
||||
<span key="clear" class={`${prefixCls}-selection__clear`} onClick={onSelectorClear}>
|
||||
{clearIcon}
|
||||
@ -109,7 +112,7 @@ export default function(modeName) {
|
||||
if (!showArrow) {
|
||||
return null;
|
||||
}
|
||||
const inputIcon = getComponentFromProp(this, 'inputIcon');
|
||||
const inputIcon = getComponent(this, 'inputIcon');
|
||||
return (
|
||||
<span key="arrow" class={`${prefixCls}-arrow`} style={{ outline: 'none' }}>
|
||||
{inputIcon}
|
||||
@ -121,8 +124,6 @@ export default function(modeName) {
|
||||
render() {
|
||||
const {
|
||||
prefixCls,
|
||||
className,
|
||||
style,
|
||||
open,
|
||||
focused,
|
||||
disabled,
|
||||
@ -132,6 +133,7 @@ export default function(modeName) {
|
||||
renderPlaceholder,
|
||||
tabindex,
|
||||
} = this.$props;
|
||||
const { class: className, style, onClick = noop } = this.$attrs;
|
||||
const {
|
||||
vcTreeSelect: { onSelectorKeyDown },
|
||||
} = this;
|
||||
@ -144,7 +146,7 @@ export default function(modeName) {
|
||||
return (
|
||||
<span
|
||||
style={style}
|
||||
onClick={getListeners(this).click || noop}
|
||||
onClick={onClick}
|
||||
class={classNames(className, prefixCls, {
|
||||
[`${prefixCls}-open`]: open,
|
||||
[`${prefixCls}-focused`]: open || focused,
|
||||
@ -152,14 +154,7 @@ export default function(modeName) {
|
||||
[`${prefixCls}-enabled`]: !disabled,
|
||||
[`${prefixCls}-allow-clear`]: allowClear,
|
||||
})}
|
||||
{...{
|
||||
directives: [
|
||||
{
|
||||
name: 'ant-ref',
|
||||
value: this.domRef,
|
||||
},
|
||||
],
|
||||
}}
|
||||
ref={this.domRef}
|
||||
role="combobox"
|
||||
aria-expanded={open}
|
||||
aria-owns={open ? ariaId : undefined}
|
||||
|
@ -2,10 +2,10 @@ import PropTypes from '../../../_util/vue-types';
|
||||
import BasePopup from '../Base/BasePopup';
|
||||
import SearchInput from '../SearchInput';
|
||||
import { createRef } from '../util';
|
||||
import { getListeners } from '../../../_util/props-util';
|
||||
|
||||
const SinglePopup = {
|
||||
name: 'SinglePopup',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
...BasePopup.props,
|
||||
...SearchInput.props,
|
||||
@ -55,28 +55,10 @@ const SinglePopup = {
|
||||
}
|
||||
|
||||
return (
|
||||
<span
|
||||
class={`${dropdownPrefixCls}-search`}
|
||||
{...{
|
||||
directives: [
|
||||
{
|
||||
name: 'ant-ref',
|
||||
value: this.searchRef,
|
||||
},
|
||||
],
|
||||
}}
|
||||
>
|
||||
<span class={`${dropdownPrefixCls}-search`} ref={this.searchRef}>
|
||||
<SearchInput
|
||||
{...{
|
||||
props: { ...this.$props, renderPlaceholder: this._renderPlaceholder },
|
||||
on: getListeners(this),
|
||||
directives: [
|
||||
{
|
||||
name: 'ant-ref',
|
||||
value: this.inputRef,
|
||||
},
|
||||
],
|
||||
}}
|
||||
{...{ ...this.$props, ...this.$attrs, renderPlaceholder: this._renderPlaceholder }}
|
||||
ref={this.inputRef}
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
@ -86,15 +68,12 @@ const SinglePopup = {
|
||||
return (
|
||||
<BasePopup
|
||||
{...{
|
||||
props: { ...this.$props, renderSearch: this._renderSearch, __propsSymbol__: Symbol() },
|
||||
on: getListeners(this),
|
||||
directives: [
|
||||
{
|
||||
name: 'ant-ref',
|
||||
value: this.popupRef,
|
||||
},
|
||||
],
|
||||
...this.$props,
|
||||
...this.$attrs,
|
||||
renderSearch: this._renderSearch,
|
||||
__propsSymbol__: Symbol(),
|
||||
}}
|
||||
ref={this.popupRef}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
@ -4,12 +4,13 @@
|
||||
* - multiple: in the selector
|
||||
* Move the code as a SearchInput for easy management.
|
||||
*/
|
||||
|
||||
import { inject } from 'vue';
|
||||
import PropTypes from '../../_util/vue-types';
|
||||
import { createRef } from './util';
|
||||
|
||||
const SearchInput = {
|
||||
name: 'SearchInput',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
open: PropTypes.bool,
|
||||
searchValue: PropTypes.string,
|
||||
@ -19,8 +20,10 @@ const SearchInput = {
|
||||
needAlign: PropTypes.bool,
|
||||
ariaId: PropTypes.string,
|
||||
},
|
||||
inject: {
|
||||
vcTreeSelect: { default: () => ({}) },
|
||||
setup() {
|
||||
return {
|
||||
vcTreeSelect: inject('vcTreeSelect', {}),
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -117,17 +120,7 @@ const SearchInput = {
|
||||
<span class={`${prefixCls}-search__field__wrap`}>
|
||||
<input
|
||||
type="text"
|
||||
{...{
|
||||
directives: [
|
||||
{
|
||||
name: 'ant-ref',
|
||||
value: this.inputRef,
|
||||
},
|
||||
{
|
||||
name: 'ant-input',
|
||||
},
|
||||
],
|
||||
}}
|
||||
ref={this.inputRef}
|
||||
onInput={handleInputChange}
|
||||
onKeydown={onSearchInputKeyDown}
|
||||
value={searchValue}
|
||||
@ -138,17 +131,7 @@ const SearchInput = {
|
||||
aria-controls={open ? ariaId : undefined}
|
||||
aria-multiline="false"
|
||||
/>
|
||||
<span
|
||||
{...{
|
||||
directives: [
|
||||
{
|
||||
name: 'ant-ref',
|
||||
value: this.mirrorInputRef,
|
||||
},
|
||||
],
|
||||
}}
|
||||
class={`${prefixCls}-search__field__mirror`}
|
||||
>
|
||||
<span ref={this.mirrorInputRef} class={`${prefixCls}-search__field__mirror`}>
|
||||
{mirrorSearchValue}
|
||||
</span>
|
||||
{renderPlaceholder && !mirrorSearchValue ? renderPlaceholder() : null}
|
||||
|
@ -18,7 +18,7 @@
|
||||
* In single mode, we should focus on the `span`
|
||||
* In multiple mode, we should focus on the `input`
|
||||
*/
|
||||
|
||||
import { provide } from 'vue';
|
||||
import shallowEqual from 'shallowequal';
|
||||
import raf from 'raf';
|
||||
import scrollIntoView from 'dom-scroll-into-view';
|
||||
@ -55,10 +55,8 @@ import SelectNode from './SelectNode';
|
||||
import {
|
||||
initDefaultProps,
|
||||
getOptionProps,
|
||||
mergeProps,
|
||||
getPropsData,
|
||||
filterEmpty,
|
||||
getListeners,
|
||||
findDOMNode,
|
||||
} from '../../_util/props-util';
|
||||
function getWatch(keys = []) {
|
||||
const watch = {};
|
||||
@ -71,6 +69,7 @@ function getWatch(keys = []) {
|
||||
}
|
||||
const Select = {
|
||||
name: 'Select',
|
||||
inheritAttrs: false,
|
||||
mixins: [BaseMixin],
|
||||
props: initDefaultProps(
|
||||
{
|
||||
@ -193,24 +192,21 @@ const Select = {
|
||||
...newState,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
provide('vcTreeSelect', {
|
||||
onSelectorFocus: this.onSelectorFocus,
|
||||
onSelectorBlur: this.onSelectorBlur,
|
||||
onSelectorKeyDown: this.onComponentKeyDown,
|
||||
onSelectorClear: this.onSelectorClear,
|
||||
onMultipleSelectorRemove: this.onMultipleSelectorRemove,
|
||||
|
||||
provide() {
|
||||
return {
|
||||
vcTreeSelect: {
|
||||
onSelectorFocus: this.onSelectorFocus,
|
||||
onSelectorBlur: this.onSelectorBlur,
|
||||
onSelectorKeyDown: this.onComponentKeyDown,
|
||||
onSelectorClear: this.onSelectorClear,
|
||||
onMultipleSelectorRemove: this.onMultipleSelectorRemove,
|
||||
onTreeNodeSelect: this.onTreeNodeSelect,
|
||||
onTreeNodeCheck: this.onTreeNodeCheck,
|
||||
onPopupKeyDown: this.onComponentKeyDown,
|
||||
|
||||
onTreeNodeSelect: this.onTreeNodeSelect,
|
||||
onTreeNodeCheck: this.onTreeNodeCheck,
|
||||
onPopupKeyDown: this.onComponentKeyDown,
|
||||
|
||||
onSearchInputChange: this.onSearchInputChange,
|
||||
onSearchInputKeyDown: this.onSearchInputKeyDown,
|
||||
},
|
||||
};
|
||||
onSearchInputChange: this.onSearchInputChange,
|
||||
onSearchInputKeyDown: this.onSearchInputKeyDown,
|
||||
});
|
||||
},
|
||||
watch: {
|
||||
...getWatch(['treeData', 'defaultValue', 'value']),
|
||||
@ -238,7 +234,7 @@ const Select = {
|
||||
const treeNode = domTreeNodes[key];
|
||||
|
||||
if (treeNode) {
|
||||
const domNode = treeNode.$el;
|
||||
const domNode = findDOMNode(treeNode);
|
||||
raf(() => {
|
||||
const popupNode = this.popup.$el;
|
||||
const triggerContainer = findPopupContainer(popupNode, `${prefixCls}-dropdown`);
|
||||
@ -267,7 +263,6 @@ const Select = {
|
||||
|
||||
methods: {
|
||||
getDerivedState(nextProps, prevState) {
|
||||
const h = this.$createElement;
|
||||
const { _prevProps: prevProps = {} } = prevState;
|
||||
const {
|
||||
treeCheckable,
|
||||
@ -302,7 +297,7 @@ const Select = {
|
||||
let treeDataChanged = false;
|
||||
let treeDataModeChanged = false;
|
||||
processState('treeData', propValue => {
|
||||
treeNodes = convertDataToTree(h, propValue);
|
||||
treeNodes = convertDataToTree(propValue);
|
||||
treeDataChanged = true;
|
||||
});
|
||||
|
||||
@ -325,7 +320,7 @@ const Select = {
|
||||
rootPId: null,
|
||||
...(treeDataSimpleMode !== true ? treeDataSimpleMode : {}),
|
||||
};
|
||||
treeNodes = convertDataToTree(h, parseSimpleTreeData(nextProps.treeData, simpleMapper));
|
||||
treeNodes = convertDataToTree(parseSimpleTreeData(nextProps.treeData, simpleMapper));
|
||||
}
|
||||
|
||||
// If `treeData` not provide, use children TreeNodes
|
||||
@ -333,7 +328,7 @@ const Select = {
|
||||
// processState('children', (propValue) => {
|
||||
// treeNodes = Array.isArray(propValue) ? propValue : [propValue]
|
||||
// })
|
||||
treeNodes = filterEmpty(this.$slots.default);
|
||||
treeNodes = this.children || [];
|
||||
}
|
||||
|
||||
// Convert `treeData` to entities
|
||||
@ -462,7 +457,6 @@ const Select = {
|
||||
}
|
||||
|
||||
newState._filteredTreeNodes = getFilterTree(
|
||||
this.$createElement,
|
||||
newState._treeNodes || prevState._treeNodes,
|
||||
searchValue,
|
||||
filterTreeNodeFn,
|
||||
@ -868,7 +862,6 @@ const Select = {
|
||||
|
||||
this.setState({
|
||||
_filteredTreeNodes: getFilterTree(
|
||||
this.$createElement,
|
||||
treeNodes,
|
||||
value,
|
||||
filterTreeNodeFn,
|
||||
@ -1012,7 +1005,7 @@ const Select = {
|
||||
}
|
||||
|
||||
// Only do the logic when `onChange` function provided
|
||||
if (getListeners(this).change) {
|
||||
if (this.$attrs.onChange) {
|
||||
let connectValueList;
|
||||
|
||||
// Get value by mode
|
||||
@ -1038,6 +1031,7 @@ const Select = {
|
||||
if (!this.isMultiple()) {
|
||||
returnValue = returnValue[0];
|
||||
}
|
||||
// this.__emit('update:value', returnValue);
|
||||
this.__emit('change', returnValue, labelList, extra);
|
||||
}
|
||||
},
|
||||
@ -1072,75 +1066,45 @@ const Select = {
|
||||
const isMultiple = this.isMultiple();
|
||||
|
||||
const passProps = {
|
||||
props: {
|
||||
...props,
|
||||
isMultiple,
|
||||
valueList,
|
||||
searchHalfCheckedKeys,
|
||||
selectorValueList: [...missValueList, ...selectorValueList],
|
||||
valueEntities,
|
||||
keyEntities,
|
||||
searchValue,
|
||||
upperSearchValue: (searchValue || '').toUpperCase(), // Perf save
|
||||
open,
|
||||
focused,
|
||||
dropdownPrefixCls: `${prefixCls}-dropdown`,
|
||||
ariaId: this.ariaId,
|
||||
},
|
||||
on: {
|
||||
...getListeners(this),
|
||||
choiceAnimationLeave: this.onChoiceAnimationLeave,
|
||||
},
|
||||
scopedSlots: this.$scopedSlots,
|
||||
...props,
|
||||
...this.$attrs,
|
||||
isMultiple,
|
||||
valueList,
|
||||
searchHalfCheckedKeys,
|
||||
selectorValueList: [...missValueList, ...selectorValueList],
|
||||
valueEntities,
|
||||
keyEntities,
|
||||
searchValue,
|
||||
upperSearchValue: (searchValue || '').toUpperCase(), // Perf save
|
||||
open,
|
||||
focused,
|
||||
dropdownPrefixCls: `${prefixCls}-dropdown`,
|
||||
ariaId: this.ariaId,
|
||||
onChoiceAnimationLeave: this.onChoiceAnimationLeave,
|
||||
vSlots: this.$slots,
|
||||
};
|
||||
const popupProps = {
|
||||
...passProps,
|
||||
treeNodes,
|
||||
filteredTreeNodes,
|
||||
// Tree expanded control
|
||||
treeExpandedKeys,
|
||||
__propsSymbol__: Symbol(),
|
||||
onTreeExpanded: this.delayForcePopupAlign,
|
||||
ref: this.setPopupRef,
|
||||
};
|
||||
const popupProps = mergeProps(passProps, {
|
||||
props: {
|
||||
treeNodes,
|
||||
filteredTreeNodes,
|
||||
// Tree expanded control
|
||||
treeExpandedKeys,
|
||||
__propsSymbol__: Symbol(),
|
||||
},
|
||||
on: {
|
||||
treeExpanded: this.delayForcePopupAlign,
|
||||
},
|
||||
directives: [
|
||||
{
|
||||
name: 'ant-ref',
|
||||
value: this.setPopupRef,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const Popup = isMultiple ? MultiplePopup : SinglePopup;
|
||||
const $popup = <Popup {...popupProps} />;
|
||||
|
||||
const Selector = isMultiple ? MultipleSelector : SingleSelector;
|
||||
const $selector = (
|
||||
<Selector
|
||||
{...passProps}
|
||||
{...{
|
||||
directives: [
|
||||
{
|
||||
name: 'ant-ref',
|
||||
value: this.selectorRef,
|
||||
},
|
||||
],
|
||||
}}
|
||||
/>
|
||||
);
|
||||
const selectTriggerProps = mergeProps(passProps, {
|
||||
props: {
|
||||
popupElement: $popup,
|
||||
dropdownVisibleChange: this.onDropdownVisibleChange,
|
||||
},
|
||||
directives: [
|
||||
{
|
||||
name: 'ant-ref',
|
||||
value: this.selectTriggerRef,
|
||||
},
|
||||
],
|
||||
});
|
||||
const $selector = <Selector {...passProps} ref={this.selectorRef} />;
|
||||
const selectTriggerProps = {
|
||||
...passProps,
|
||||
popupElement: $popup,
|
||||
dropdownVisibleChange: this.onDropdownVisibleChange,
|
||||
ref: this.selectTriggerRef,
|
||||
};
|
||||
return <SelectTrigger {...selectTriggerProps}>{$selector}</SelectTrigger>;
|
||||
},
|
||||
};
|
||||
|
@ -4,29 +4,10 @@ import { TreeNode } from '../../vc-tree';
|
||||
* Let's use SelectNode instead of TreeNode
|
||||
* since TreeNode is so confuse here.
|
||||
*/
|
||||
export default {
|
||||
name: 'SelectNode',
|
||||
functional: true,
|
||||
isTreeNode: true,
|
||||
props: TreeNode.props,
|
||||
render(h, context) {
|
||||
const { props, slots, listeners, data, scopedSlots } = context;
|
||||
const $slots = slots() || {};
|
||||
const children = $slots.default;
|
||||
const slotsKey = Object.keys($slots);
|
||||
const scopedSlotsTemp = {}; // for vue 2.5.x
|
||||
slotsKey.forEach(name => {
|
||||
scopedSlotsTemp[name] = () => $slots[name];
|
||||
});
|
||||
const treeNodeProps = {
|
||||
...data,
|
||||
on: { ...listeners, ...data.nativeOn },
|
||||
props,
|
||||
scopedSlots: {
|
||||
...scopedSlotsTemp,
|
||||
...scopedSlots,
|
||||
},
|
||||
};
|
||||
return <TreeNode {...treeNodeProps}>{children}</TreeNode>;
|
||||
},
|
||||
};
|
||||
function SelectNode(_, { attrs, slots }) {
|
||||
return <TreeNode {...attrs} vSlots={slots} />;
|
||||
}
|
||||
|
||||
SelectNode.isTreeNode = true;
|
||||
SelectNode.inheritAttrs = false;
|
||||
export default SelectNode;
|
||||
|
@ -1,8 +1,8 @@
|
||||
import PropTypes from '../../_util/vue-types';
|
||||
|
||||
import Trigger from '../../vc-trigger';
|
||||
import { createRef } from './util';
|
||||
import classNames from 'classnames';
|
||||
import { getSlot } from '../../_util/props-util';
|
||||
|
||||
const BUILT_IN_PLACEMENTS = {
|
||||
bottomLeft: {
|
||||
@ -27,6 +27,7 @@ const BUILT_IN_PLACEMENTS = {
|
||||
|
||||
const SelectTrigger = {
|
||||
name: 'SelectTrigger',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
// Pass by outside user props
|
||||
disabled: PropTypes.bool,
|
||||
@ -93,14 +94,7 @@ const SelectTrigger = {
|
||||
}
|
||||
return (
|
||||
<Trigger
|
||||
{...{
|
||||
directives: [
|
||||
{
|
||||
name: 'ant-ref',
|
||||
value: this.triggerRef,
|
||||
},
|
||||
],
|
||||
}}
|
||||
ref={this.triggerRef}
|
||||
action={disabled ? [] : ['click']}
|
||||
popupPlacement="bottomLeft"
|
||||
builtinPlacements={BUILT_IN_PLACEMENTS}
|
||||
@ -118,7 +112,7 @@ const SelectTrigger = {
|
||||
})}
|
||||
popupStyle={dropdownStyle}
|
||||
>
|
||||
{this.$slots.default}
|
||||
{getSlot(this)}
|
||||
</Trigger>
|
||||
);
|
||||
},
|
||||
|
@ -1,10 +1,12 @@
|
||||
import classNames from 'classnames';
|
||||
import PropTypes from '../../../../_util/vue-types';
|
||||
import { toTitle, UNSELECTABLE_ATTRIBUTE, UNSELECTABLE_STYLE } from '../../util';
|
||||
import { getComponentFromProp, getListeners } from '../../../../_util/props-util';
|
||||
import { getComponent } from '../../../../_util/props-util';
|
||||
import BaseMixin from '../../../../_util/BaseMixin';
|
||||
|
||||
const Selection = {
|
||||
mixins: [BaseMixin],
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
prefixCls: PropTypes.string,
|
||||
maxTagTextLength: PropTypes.number,
|
||||
@ -28,18 +30,18 @@ const Selection = {
|
||||
if (maxTagTextLength && typeof content === 'string' && content.length > maxTagTextLength) {
|
||||
content = `${content.slice(0, maxTagTextLength)}...`;
|
||||
}
|
||||
|
||||
const { class: className, style, onRemove } = this.$attrs;
|
||||
return (
|
||||
<li
|
||||
style={UNSELECTABLE_STYLE}
|
||||
{...{ attrs: UNSELECTABLE_ATTRIBUTE }}
|
||||
style={{ ...UNSELECTABLE_STYLE, ...style }}
|
||||
{...UNSELECTABLE_ATTRIBUTE}
|
||||
role="menuitem"
|
||||
class={`${prefixCls}-selection__choice`}
|
||||
class={classNames(`${prefixCls}-selection__choice`, className)}
|
||||
title={toTitle(label)}
|
||||
>
|
||||
{getListeners(this).remove && (
|
||||
{onRemove && (
|
||||
<span class={`${prefixCls}-selection__choice__remove`} onClick={this.onRemove}>
|
||||
{getComponentFromProp(this, 'removeIcon')}
|
||||
{getComponent(this, 'removeIcon')}
|
||||
</span>
|
||||
)}
|
||||
<span class={`${prefixCls}-selection__choice__content`}>{content}</span>
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { inject, TransitionGroup } from 'vue';
|
||||
import PropTypes from '../../../../_util/vue-types';
|
||||
import { createRef } from '../../util';
|
||||
import generateSelector, { selectorPropTypes } from '../../Base/BaseSelector';
|
||||
import SearchInput from '../../SearchInput';
|
||||
import Selection from './Selection';
|
||||
import { getComponentFromProp, getListeners } from '../../../../_util/props-util';
|
||||
import { getComponent, getSlot } from '../../../../_util/props-util';
|
||||
import getTransitionProps from '../../../../_util/getTransitionProps';
|
||||
import BaseMixin from '../../../../_util/BaseMixin';
|
||||
const TREE_SELECT_EMPTY_VALUE_KEY = 'RC_TREE_SELECT_EMPTY_VALUE_KEY';
|
||||
@ -15,7 +16,9 @@ const Selector = generateSelector('multiple');
|
||||
// }
|
||||
|
||||
const MultipleSelector = {
|
||||
name: 'MultipleSelector',
|
||||
mixins: [BaseMixin],
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
...selectorPropTypes(),
|
||||
...SearchInput.props,
|
||||
@ -28,8 +31,10 @@ const MultipleSelector = {
|
||||
|
||||
// onChoiceAnimationLeave: PropTypes.func,
|
||||
},
|
||||
inject: {
|
||||
vcTreeSelect: { default: () => ({}) },
|
||||
setup() {
|
||||
return {
|
||||
vcTreeSelect: inject('vcTreeSelect', {}),
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.inputRef = createRef();
|
||||
@ -85,11 +90,10 @@ const MultipleSelector = {
|
||||
labelInValue,
|
||||
maxTagCount,
|
||||
} = this.$props;
|
||||
const children = getSlot(this);
|
||||
const {
|
||||
vcTreeSelect: { onMultipleSelectorRemove },
|
||||
$slots,
|
||||
} = this;
|
||||
const listeners = getListeners(this);
|
||||
// Check if `maxTagCount` is set
|
||||
let myValueList = selectorValueList;
|
||||
if (maxTagCount >= 0) {
|
||||
@ -99,23 +103,21 @@ const MultipleSelector = {
|
||||
const selectedValueNodes = myValueList.map(({ label, value }) => (
|
||||
<Selection
|
||||
{...{
|
||||
props: {
|
||||
...this.$props,
|
||||
label,
|
||||
value,
|
||||
},
|
||||
on: { ...listeners, remove: onMultipleSelectorRemove },
|
||||
...this.$props,
|
||||
label,
|
||||
value,
|
||||
onRemove: onMultipleSelectorRemove,
|
||||
}}
|
||||
key={value || TREE_SELECT_EMPTY_VALUE_KEY}
|
||||
>
|
||||
{$slots.default}
|
||||
{children}
|
||||
</Selection>
|
||||
));
|
||||
|
||||
// Rest node count
|
||||
if (maxTagCount >= 0 && maxTagCount < selectorValueList.length) {
|
||||
let content = `+ ${selectorValueList.length - maxTagCount} ...`;
|
||||
const maxTagPlaceholder = getComponentFromProp(this, 'maxTagPlaceholder', {}, false);
|
||||
const maxTagPlaceholder = getComponent(this, 'maxTagPlaceholder', {}, false);
|
||||
if (typeof maxTagPlaceholder === 'string') {
|
||||
content = maxTagPlaceholder;
|
||||
} else if (typeof maxTagPlaceholder === 'function') {
|
||||
@ -128,16 +130,13 @@ const MultipleSelector = {
|
||||
const restNodeSelect = (
|
||||
<Selection
|
||||
{...{
|
||||
props: {
|
||||
...this.$props,
|
||||
label: content,
|
||||
value: null,
|
||||
},
|
||||
on: listeners,
|
||||
...this.$props,
|
||||
label: content,
|
||||
value: null,
|
||||
}}
|
||||
key="rc-tree-select-internal-max-tag-counter"
|
||||
>
|
||||
{$slots.default}
|
||||
{children}
|
||||
</Selection>
|
||||
);
|
||||
|
||||
@ -148,20 +147,13 @@ const MultipleSelector = {
|
||||
<li class={`${prefixCls}-search ${prefixCls}-search--inline`} key="__input">
|
||||
<SearchInput
|
||||
{...{
|
||||
props: {
|
||||
...this.$props,
|
||||
needAlign: true,
|
||||
},
|
||||
on: listeners,
|
||||
directives: [
|
||||
{
|
||||
name: 'ant-ref',
|
||||
value: this.inputRef,
|
||||
},
|
||||
],
|
||||
...this.$props,
|
||||
...this.$attrs,
|
||||
needAlign: true,
|
||||
}}
|
||||
ref={this.inputRef}
|
||||
>
|
||||
{$slots.default}
|
||||
{children}
|
||||
</SearchInput>
|
||||
</li>,
|
||||
);
|
||||
@ -169,12 +161,12 @@ const MultipleSelector = {
|
||||
if (choiceTransitionName) {
|
||||
const transitionProps = getTransitionProps(choiceTransitionName, {
|
||||
tag: 'ul',
|
||||
afterLeave: this.onChoiceAnimationLeave,
|
||||
onAfterLeave: this.onChoiceAnimationLeave,
|
||||
});
|
||||
return (
|
||||
<transition-group class={className} {...transitionProps}>
|
||||
<TransitionGroup class={className} {...transitionProps}>
|
||||
{selectedValueNodes}
|
||||
</transition-group>
|
||||
</TransitionGroup>
|
||||
);
|
||||
}
|
||||
return (
|
||||
@ -186,22 +178,18 @@ const MultipleSelector = {
|
||||
},
|
||||
|
||||
render() {
|
||||
const { $slots } = this;
|
||||
const listeners = getListeners(this);
|
||||
return (
|
||||
<Selector
|
||||
{...{
|
||||
props: {
|
||||
...this.$props,
|
||||
tabindex: -1,
|
||||
showArrow: false,
|
||||
renderSelection: this.renderSelection,
|
||||
renderPlaceholder: this._renderPlaceholder,
|
||||
},
|
||||
on: listeners,
|
||||
...this.$props,
|
||||
...this.$attrs,
|
||||
tabindex: -1,
|
||||
showArrow: false,
|
||||
renderSelection: this.renderSelection,
|
||||
renderPlaceholder: this._renderPlaceholder,
|
||||
}}
|
||||
>
|
||||
{$slots.default}
|
||||
{getSlot(this)}
|
||||
</Selector>
|
||||
);
|
||||
},
|
||||
|
@ -1,11 +1,12 @@
|
||||
import generateSelector, { selectorPropTypes } from '../Base/BaseSelector';
|
||||
import { toTitle } from '../util';
|
||||
import { getOptionProps, getListeners } from '../../../_util/props-util';
|
||||
import { getOptionProps } from '../../../_util/props-util';
|
||||
import { createRef } from '../util';
|
||||
const Selector = generateSelector('single');
|
||||
|
||||
const SingleSelector = {
|
||||
name: 'SingleSelector',
|
||||
inheritAttrs: false,
|
||||
props: selectorPropTypes(),
|
||||
created() {
|
||||
this.selectorRef = createRef();
|
||||
@ -43,17 +44,10 @@ const SingleSelector = {
|
||||
|
||||
render() {
|
||||
const props = {
|
||||
props: {
|
||||
...getOptionProps(this),
|
||||
renderSelection: this.renderSelection,
|
||||
},
|
||||
on: getListeners(this),
|
||||
directives: [
|
||||
{
|
||||
name: 'ant-ref',
|
||||
value: this.selectorRef,
|
||||
},
|
||||
],
|
||||
...getOptionProps(this),
|
||||
...this.$attrs,
|
||||
renderSelection: this.renderSelection,
|
||||
ref: this.selectorRef,
|
||||
};
|
||||
return <Selector {...props} />;
|
||||
},
|
||||
|
@ -1,5 +1,4 @@
|
||||
import warning from 'warning';
|
||||
import omit from 'omit.js';
|
||||
import {
|
||||
convertDataToTree as vcConvertDataToTree,
|
||||
convertTreeToEntities as vcConvertTreeToEntities,
|
||||
@ -7,7 +6,7 @@ import {
|
||||
} from '../../vc-tree/src/util';
|
||||
import { hasClass } from '../../vc-util/Dom/class';
|
||||
import { SHOW_CHILD, SHOW_PARENT } from './strategies';
|
||||
import { getSlots, getPropsData, isEmptyElement } from '../../_util/props-util';
|
||||
import { getSlot, getPropsData, isEmptyElement } from '../../_util/props-util';
|
||||
|
||||
let warnDeprecatedLabel = false;
|
||||
|
||||
@ -203,7 +202,7 @@ export function cleanEntity({ node, pos, children }) {
|
||||
* we have to convert `treeNodes > data > treeNodes` to keep the key.
|
||||
* Such performance hungry!
|
||||
*/
|
||||
export function getFilterTree(h, treeNodes, searchValue, filterFunc, valueEntities, Component) {
|
||||
export function getFilterTree(treeNodes, searchValue, filterFunc, valueEntities, Component) {
|
||||
if (!searchValue) {
|
||||
return null;
|
||||
}
|
||||
@ -215,13 +214,13 @@ export function getFilterTree(h, treeNodes, searchValue, filterFunc, valueEntiti
|
||||
if (filterFunc(searchValue, node)) {
|
||||
match = true;
|
||||
}
|
||||
let children = getSlots(node).default;
|
||||
let children = getSlot(node);
|
||||
children = ((typeof children === 'function' ? children() : children) || [])
|
||||
.map(mapFilteredNodeToData)
|
||||
.filter(n => n);
|
||||
if (children.length || match) {
|
||||
return (
|
||||
<Component {...node.data} key={valueEntities[getPropsData(node).value].key}>
|
||||
<Component {...node.props} key={valueEntities[getPropsData(node).value].key}>
|
||||
{children}
|
||||
</Component>
|
||||
);
|
||||
@ -341,18 +340,8 @@ export function formatSelectorValue(valueList, props, valueEntities) {
|
||||
* This will change the label to title value
|
||||
*/
|
||||
function processProps(props) {
|
||||
const { title, label, value, class: cls, style, on = {} } = props;
|
||||
let key = props.key;
|
||||
if (!key && (key === undefined || key === null)) {
|
||||
key = value;
|
||||
}
|
||||
const p = {
|
||||
props: omit(props, ['on', 'key', 'class', 'className', 'style']),
|
||||
on,
|
||||
class: cls || props.className,
|
||||
style,
|
||||
key,
|
||||
};
|
||||
const { title, label, key, value } = props;
|
||||
const cloneProps = { ...props };
|
||||
// Warning user not to use deprecated label prop.
|
||||
if (label && !title) {
|
||||
if (!warnDeprecatedLabel) {
|
||||
@ -360,14 +349,18 @@ function processProps(props) {
|
||||
warnDeprecatedLabel = true;
|
||||
}
|
||||
|
||||
p.props.title = label;
|
||||
cloneProps.title = label;
|
||||
}
|
||||
|
||||
return p;
|
||||
if (!key && (key === undefined || key === null)) {
|
||||
cloneProps.key = value;
|
||||
}
|
||||
|
||||
return cloneProps;
|
||||
}
|
||||
|
||||
export function convertDataToTree(h, treeData) {
|
||||
return vcConvertDataToTree(h, treeData, { processProps });
|
||||
export function convertDataToTree(treeData) {
|
||||
return vcConvertDataToTree(treeData, { processProps });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -40,7 +40,7 @@ export function getPosition(level, index) {
|
||||
}
|
||||
|
||||
export function isTreeNode(node) {
|
||||
return typeof node.type === 'object' && node.type.isTreeNode;
|
||||
return node.type && node.type.isTreeNode;
|
||||
}
|
||||
|
||||
export function getNodeChildren(children = []) {
|
||||
|
@ -92,6 +92,7 @@ export default {
|
||||
};
|
||||
});
|
||||
this._component = null;
|
||||
this.focusTime = null;
|
||||
return {
|
||||
prevPopupVisible: popupVisible,
|
||||
sPopupVisible: popupVisible,
|
||||
|
@ -4,7 +4,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import demo from '../antdv-demo/docs/tree/demo/directory';
|
||||
import demo from '../antdv-demo/docs/tree-select/demo/treeData';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -28,6 +28,7 @@ import {
|
||||
Card,
|
||||
Avatar,
|
||||
Tree,
|
||||
TreeSelect,
|
||||
notification,
|
||||
message,
|
||||
} from 'ant-design-vue';
|
||||
@ -45,11 +46,11 @@ const app = createApp(App);
|
||||
app.config.globalProperties.$notification = notification;
|
||||
app.config.globalProperties.$message = message;
|
||||
app
|
||||
.component('demo-sort', { ...basic })
|
||||
.component('md', { ...basic })
|
||||
.component('api', { ...basic })
|
||||
.component('CN', { ...basic })
|
||||
.component('US', { ...basic })
|
||||
// .component('demo-sort', { ...basic })
|
||||
// .component('md', { ...basic })
|
||||
// .component('api', { ...basic })
|
||||
// .component('CN', { ...basic })
|
||||
// .component('US', { ...basic })
|
||||
.use(Pagination)
|
||||
.use(Select)
|
||||
.use(Spin)
|
||||
@ -76,4 +77,5 @@ app
|
||||
.use(Avatar)
|
||||
.use(Card)
|
||||
.use(Tree)
|
||||
.use(TreeSelect)
|
||||
.mount('#app');
|
||||
|
Loading…
Reference in New Issue
Block a user