feat: update autocomplete
parent
5e80e8019e
commit
ad6f343376
|
@ -2,6 +2,7 @@ import isPlainObject from 'lodash/isPlainObject';
|
|||
import classNames from 'classnames';
|
||||
import { isVNode, Fragment, Comment, Text } from 'vue';
|
||||
import { camelize, hyphenate, isOn, resolvePropValue } from './util';
|
||||
import isValid from './isValid';
|
||||
// function getType(fn) {
|
||||
// const match = fn && fn.toString().match(/^\s*function (\w+)/);
|
||||
// return match ? match[1] : '';
|
||||
|
@ -82,6 +83,8 @@ const flattenChildren = (children = [], filterEmpty = true) => {
|
|||
} else if (!filterEmpty) {
|
||||
res.push(child);
|
||||
}
|
||||
} else if (isValid(child)) {
|
||||
res.push(child);
|
||||
}
|
||||
});
|
||||
return res;
|
||||
|
|
|
@ -1,53 +1,59 @@
|
|||
import PropTypes from '../_util/vue-types';
|
||||
import { cloneElement } from '../_util/vnode';
|
||||
import { getOptionProps, getListeners } from '../_util/props-util';
|
||||
function chaining(...fns) {
|
||||
return function(...args) {
|
||||
// eslint-disable-line
|
||||
// eslint-disable-line
|
||||
for (let i = 0; i < fns.length; i++) {
|
||||
if (fns[i] && typeof fns[i] === 'function') {
|
||||
fns[i].apply(this, args);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
export default {
|
||||
name: 'InputElement',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
value: PropTypes.any,
|
||||
disabled: PropTypes.bool,
|
||||
placeholder: PropTypes.string,
|
||||
},
|
||||
render() {
|
||||
const { $slots = {}, $attrs = {}, placeholder } = this;
|
||||
const listeners = getListeners(this);
|
||||
const props = getOptionProps(this);
|
||||
const value = props.value === undefined ? '' : props.value;
|
||||
const children = $slots.default[0];
|
||||
const { componentOptions = {} } = $slots.default[0];
|
||||
const { listeners: events = {} } = componentOptions;
|
||||
const newEvent = { ...events };
|
||||
import { flattenChildren } from '../_util/props-util';
|
||||
// function chaining(...fns) {
|
||||
// return function(...args) {
|
||||
// // eslint-disable-line
|
||||
// // eslint-disable-line
|
||||
// for (let i = 0; i < fns.length; i++) {
|
||||
// if (fns[i] && typeof fns[i] === 'function') {
|
||||
// fns[i].apply(this, args);
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// export default {
|
||||
// name: 'InputElement',
|
||||
// inheritAttrs: false,
|
||||
// props: {
|
||||
// value: PropTypes.any,
|
||||
// disabled: PropTypes.bool,
|
||||
// placeholder: PropTypes.string,
|
||||
// },
|
||||
// render() {
|
||||
// const { $slots = {}, $attrs = {}, placeholder } = this;
|
||||
// const listeners = getListeners(this);
|
||||
// const props = getOptionProps(this);
|
||||
// const value = props.value === undefined ? '' : props.value;
|
||||
// const children = getSlot(this)[0];
|
||||
// const { componentOptions = {} } = $slots.default[0];
|
||||
// const { listeners: events = {} } = componentOptions;
|
||||
// const newEvent = { ...events };
|
||||
|
||||
for (const [eventName, event] of Object.entries(listeners)) {
|
||||
newEvent[eventName] = chaining(event, events[eventName]);
|
||||
}
|
||||
const attrs = { ...$attrs, value };
|
||||
// https://github.com/vueComponent/ant-design-vue/issues/1761
|
||||
delete props.placeholder;
|
||||
if (placeholder) {
|
||||
props.placeholder = placeholder;
|
||||
attrs.placeholder = placeholder;
|
||||
}
|
||||
return cloneElement(children, {
|
||||
domProps: {
|
||||
value,
|
||||
},
|
||||
props,
|
||||
on: newEvent,
|
||||
attrs,
|
||||
ref: 'ele',
|
||||
});
|
||||
},
|
||||
// for (const [eventName, event] of Object.entries(listeners)) {
|
||||
// newEvent[eventName] = chaining(event, events[eventName]);
|
||||
// }
|
||||
// const attrs = { ...$attrs, value };
|
||||
// // https://github.com/vueComponent/ant-design-vue/issues/1761
|
||||
// delete props.placeholder;
|
||||
// if (placeholder) {
|
||||
// props.placeholder = placeholder;
|
||||
// attrs.placeholder = placeholder;
|
||||
// }
|
||||
// return cloneElement(children, {
|
||||
// domProps: {
|
||||
// value,
|
||||
// },
|
||||
// props,
|
||||
// on: newEvent,
|
||||
// attrs,
|
||||
// ref: 'ele',
|
||||
// });
|
||||
// },
|
||||
// };
|
||||
|
||||
const InputElement = (_, { attrs, slots }) => {
|
||||
const children = flattenChildren(slots.default?.())[0];
|
||||
return cloneElement(children, { ...attrs });
|
||||
};
|
||||
InputElement.inheritAttrs = false;
|
||||
export default InputElement;
|
||||
|
|
|
@ -1,17 +1,11 @@
|
|||
import { inject, provide } from 'vue';
|
||||
import { Option, OptGroup } from '../vc-select';
|
||||
import Select, { AbstractSelectProps, SelectValue } from '../select';
|
||||
import Input from '../input';
|
||||
import InputElement from './InputElement';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import { ConfigConsumerProps } from '../config-provider';
|
||||
import {
|
||||
getComponentFromProp,
|
||||
getOptionProps,
|
||||
filterEmpty,
|
||||
isValidElement,
|
||||
getListeners,
|
||||
} from '../_util/props-util';
|
||||
import Base from '../base';
|
||||
import { getComponent, getOptionProps, isValidElement, getSlot } from '../_util/props-util';
|
||||
|
||||
// const DataSourceItemObject = PropTypes.shape({
|
||||
// value: String,
|
||||
|
@ -26,6 +20,9 @@ import Base from '../base';
|
|||
// onChange?: React.FormEventHandler<any>;
|
||||
// value: any;
|
||||
// }
|
||||
function isSelectOptionOrSelectOptGroup(child) {
|
||||
return child && child.type && (child.type.isSelectOption || child.type.isSelectOptGroup);
|
||||
}
|
||||
|
||||
const AutoCompleteProps = {
|
||||
...AbstractSelectProps(),
|
||||
|
@ -41,6 +38,7 @@ const AutoCompleteProps = {
|
|||
|
||||
const AutoComplete = {
|
||||
name: 'AAutoComplete',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
...AutoCompleteProps,
|
||||
prefixCls: PropTypes.string.def('ant-select'),
|
||||
|
@ -55,50 +53,53 @@ const AutoComplete = {
|
|||
},
|
||||
Option: { ...Option, name: 'AAutoCompleteOption' },
|
||||
OptGroup: { ...OptGroup, name: 'AAutoCompleteOptGroup' },
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'change',
|
||||
},
|
||||
inject: {
|
||||
configProvider: { default: () => ConfigConsumerProps },
|
||||
},
|
||||
provide() {
|
||||
// model: {
|
||||
// prop: 'value',
|
||||
// event: 'change',
|
||||
// },
|
||||
setup() {
|
||||
return {
|
||||
savePopupRef: this.savePopupRef,
|
||||
configProvider: inject('configProvider', ConfigConsumerProps),
|
||||
};
|
||||
},
|
||||
created() {
|
||||
provide('savePopupRef', this.savePopupRef);
|
||||
},
|
||||
methods: {
|
||||
savePopupRef(ref) {
|
||||
this.popupRef = ref;
|
||||
},
|
||||
|
||||
saveSelect(node) {
|
||||
this.select = node;
|
||||
},
|
||||
getInputElement() {
|
||||
const { $slots, placeholder } = this;
|
||||
const children = filterEmpty($slots.default);
|
||||
const { placeholder } = this;
|
||||
const children = getSlot(this);
|
||||
const element = children.length ? children[0] : <Input lazy={false} />;
|
||||
return <InputElement placeholder={placeholder}>{element}</InputElement>;
|
||||
},
|
||||
|
||||
focus() {
|
||||
if (this.$refs.select) {
|
||||
this.$refs.select.focus();
|
||||
if (this.select) {
|
||||
this.select.focus();
|
||||
}
|
||||
},
|
||||
|
||||
blur() {
|
||||
if (this.$refs.select) {
|
||||
this.$refs.select.blur();
|
||||
if (this.select) {
|
||||
this.select.blur();
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
render() {
|
||||
const { size, prefixCls: customizePrefixCls, optionLabelProp, dataSource, $slots } = this;
|
||||
const { size, prefixCls: customizePrefixCls, optionLabelProp, dataSource } = this;
|
||||
|
||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||
const prefixCls = getPrefixCls('select', customizePrefixCls);
|
||||
|
||||
const { class: className } = this.$attrs;
|
||||
const cls = {
|
||||
[className]: !!className,
|
||||
[`${prefixCls}-lg`]: size === 'large',
|
||||
[`${prefixCls}-sm`]: size === 'small',
|
||||
[`${prefixCls}-show-search`]: true,
|
||||
|
@ -106,8 +107,8 @@ const AutoComplete = {
|
|||
};
|
||||
|
||||
let options;
|
||||
const childArray = filterEmpty($slots.dataSource);
|
||||
if (childArray.length) {
|
||||
const childArray = getSlot(this, 'dataSource');
|
||||
if (childArray.length && isSelectOptionOrSelectOptGroup(childArray[0])) {
|
||||
options = childArray;
|
||||
} else {
|
||||
options = dataSource
|
||||
|
@ -129,28 +130,25 @@ const AutoComplete = {
|
|||
: [];
|
||||
}
|
||||
const selectProps = {
|
||||
props: {
|
||||
...getOptionProps(this),
|
||||
mode: Select.SECRET_COMBOBOX_MODE_DO_NOT_USE,
|
||||
optionLabelProp,
|
||||
getInputElement: this.getInputElement,
|
||||
notFoundContent: getComponentFromProp(this, 'notFoundContent'),
|
||||
placeholder: '',
|
||||
},
|
||||
...getOptionProps(this),
|
||||
...this.$attrs,
|
||||
mode: Select.SECRET_COMBOBOX_MODE_DO_NOT_USE,
|
||||
optionLabelProp,
|
||||
getInputElement: this.getInputElement,
|
||||
notFoundContent: getComponent(this, 'notFoundContent'),
|
||||
placeholder: '',
|
||||
class: cls,
|
||||
ref: 'select',
|
||||
on: getListeners(this),
|
||||
ref: this.saveSelect,
|
||||
};
|
||||
return <Select {...selectProps}>{options}</Select>;
|
||||
},
|
||||
};
|
||||
|
||||
/* istanbul ignore next */
|
||||
AutoComplete.install = function(Vue) {
|
||||
Vue.use(Base);
|
||||
Vue.component(AutoComplete.name, AutoComplete);
|
||||
Vue.component(AutoComplete.Option.name, AutoComplete.Option);
|
||||
Vue.component(AutoComplete.OptGroup.name, AutoComplete.OptGroup);
|
||||
AutoComplete.install = function(app) {
|
||||
app.component(AutoComplete.name, AutoComplete);
|
||||
app.component(AutoComplete.Option.name, AutoComplete.Option);
|
||||
app.component(AutoComplete.OptGroup.name, AutoComplete.OptGroup);
|
||||
};
|
||||
|
||||
export default AutoComplete;
|
||||
|
|
|
@ -33,7 +33,8 @@ export function getPropValue(child, prop) {
|
|||
return getValuePropValue(child);
|
||||
}
|
||||
if (prop === 'children') {
|
||||
const newChild = cloneElement(getComponent(child));
|
||||
const temp = getComponent(child);
|
||||
const newChild = isVNode(temp) ? cloneElement(temp) : temp;
|
||||
if (isVNode(newChild) && newChild.type === Text) {
|
||||
return newChild.children;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import '@babel/polyfill';
|
|||
import { createApp } from 'vue';
|
||||
import App from './App.vue';
|
||||
import {
|
||||
AutoComplete,
|
||||
Radio,
|
||||
Spin,
|
||||
Select,
|
||||
|
@ -49,4 +50,5 @@ app
|
|||
.use(Row)
|
||||
.use(Radio)
|
||||
.use(InputNumber)
|
||||
.use(AutoComplete)
|
||||
.mount('#app');
|
||||
|
|
Loading…
Reference in New Issue