feat: udpate formmodel
parent
a3c8930b39
commit
6cad9c3cc0
|
@ -1,10 +1,10 @@
|
|||
import { filterEmpty } from './props-util';
|
||||
import { cloneVNode } from 'vue';
|
||||
|
||||
export function cloneElement(n, nodeProps = {}, override = true) {
|
||||
let ele = n;
|
||||
if (Array.isArray(n)) {
|
||||
ele = filterEmpty(n)[0];
|
||||
export function cloneElement(vnode, nodeProps = {}, override = true) {
|
||||
let ele = vnode;
|
||||
if (Array.isArray(vnode)) {
|
||||
ele = filterEmpty(vnode)[0];
|
||||
}
|
||||
if (!ele) {
|
||||
return null;
|
||||
|
@ -15,3 +15,7 @@ export function cloneElement(n, nodeProps = {}, override = true) {
|
|||
node.props = override ? { ...node.props, ...nodeProps } : node.props;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function cloneVNodes(vnodes, nodeProps = {}, override = true) {
|
||||
return vnodes.map(vnode => cloneElement(vnode, nodeProps, override));
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { inject, provide } from 'vue';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import classNames from 'classnames';
|
||||
import { ColProps } from '../grid/Col';
|
||||
import isRegExp from 'lodash/isRegExp';
|
||||
import warning from '../_util/warning';
|
||||
import FormItem from './FormItem';
|
||||
import { initDefaultProps, getListeners } from '../_util/props-util';
|
||||
import { initDefaultProps, getListeners, getSlot } from '../_util/props-util';
|
||||
import { ConfigConsumerProps } from '../config-provider';
|
||||
|
||||
export const FormProps = {
|
||||
|
@ -48,6 +49,7 @@ export const ValidationRule = {
|
|||
|
||||
const Form = {
|
||||
name: 'AFormModel',
|
||||
inheritAttrs: false,
|
||||
props: initDefaultProps(FormProps, {
|
||||
layout: 'horizontal',
|
||||
hideRequiredMark: false,
|
||||
|
@ -56,15 +58,14 @@ const Form = {
|
|||
Item: FormItem,
|
||||
created() {
|
||||
this.fields = [];
|
||||
this.form = undefined;
|
||||
provide('FormContext', this);
|
||||
},
|
||||
provide() {
|
||||
setup() {
|
||||
return {
|
||||
FormContext: this,
|
||||
configProvider: inject('configProvider', ConfigConsumerProps),
|
||||
};
|
||||
},
|
||||
inject: {
|
||||
configProvider: { default: () => ConfigConsumerProps },
|
||||
},
|
||||
watch: {
|
||||
rules() {
|
||||
if (this.validateOnRuleChange) {
|
||||
|
@ -164,19 +165,20 @@ const Form = {
|
|||
},
|
||||
|
||||
render() {
|
||||
const { prefixCls: customizePrefixCls, hideRequiredMark, layout, onSubmit, $slots } = this;
|
||||
const { prefixCls: customizePrefixCls, hideRequiredMark, layout, onSubmit } = this;
|
||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||
const prefixCls = getPrefixCls('form', customizePrefixCls);
|
||||
const { class: className, onSubmit: originSubmit, ...restProps } = this.$attrs;
|
||||
|
||||
const formClassName = classNames(prefixCls, {
|
||||
const formClassName = classNames(prefixCls, className, {
|
||||
[`${prefixCls}-horizontal`]: layout === 'horizontal',
|
||||
[`${prefixCls}-vertical`]: layout === 'vertical',
|
||||
[`${prefixCls}-inline`]: layout === 'inline',
|
||||
[`${prefixCls}-hide-required-mark`]: hideRequiredMark,
|
||||
});
|
||||
return (
|
||||
<form onSubmit={onSubmit} class={formClassName}>
|
||||
{$slots.default}
|
||||
<form onSubmit={onSubmit} class={formClassName} {...restProps}>
|
||||
{getSlot(this)}
|
||||
</form>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
import { inject } from 'vue';
|
||||
import AsyncValidator from 'async-validator';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import { ColProps } from '../grid/Col';
|
||||
import {
|
||||
initDefaultProps,
|
||||
getComponentFromProp,
|
||||
getComponent,
|
||||
getOptionProps,
|
||||
getEvents,
|
||||
filterEmpty,
|
||||
isValidElement,
|
||||
getSlot,
|
||||
} from '../_util/props-util';
|
||||
import BaseMixin from '../_util/BaseMixin';
|
||||
import { ConfigConsumerProps } from '../config-provider';
|
||||
|
@ -63,15 +64,18 @@ export const FormItemProps = {
|
|||
|
||||
export default {
|
||||
name: 'AFormModelItem',
|
||||
__ANT_NEW_FORM_ITEM: true,
|
||||
mixins: [BaseMixin],
|
||||
inheritAttrs: false,
|
||||
__ANT_NEW_FORM_ITEM: true,
|
||||
props: initDefaultProps(FormItemProps, {
|
||||
hasFeedback: false,
|
||||
autoLink: true,
|
||||
}),
|
||||
inject: {
|
||||
configProvider: { default: () => ConfigConsumerProps },
|
||||
FormContext: { default: () => ({}) },
|
||||
setup() {
|
||||
return {
|
||||
configProvider: inject('configProvider', ConfigConsumerProps),
|
||||
FormContext: inject('FormContext', {}),
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -216,43 +220,39 @@ export default {
|
|||
},
|
||||
},
|
||||
render() {
|
||||
const { $slots, $scopedSlots } = this;
|
||||
const props = getOptionProps(this);
|
||||
const label = getComponentFromProp(this, 'label');
|
||||
const extra = getComponentFromProp(this, 'extra');
|
||||
const help = getComponentFromProp(this, 'help');
|
||||
const { autoLink, ...props } = getOptionProps(this);
|
||||
const label = getComponent(this, 'label');
|
||||
const extra = getComponent(this, 'extra');
|
||||
const help = getComponent(this, 'help');
|
||||
const formProps = {
|
||||
props: {
|
||||
...props,
|
||||
label,
|
||||
extra,
|
||||
validateStatus: this.validateState,
|
||||
help: this.validateMessage || help,
|
||||
required: this.isRequired || props.required,
|
||||
},
|
||||
...this.$attrs,
|
||||
...props,
|
||||
label,
|
||||
extra,
|
||||
validateStatus: this.validateState,
|
||||
help: this.validateMessage || help,
|
||||
required: this.isRequired || props.required,
|
||||
};
|
||||
const children = filterEmpty($scopedSlots.default ? $scopedSlots.default() : $slots.default);
|
||||
const children = getSlot(this);
|
||||
let firstChildren = children[0];
|
||||
if (this.prop && this.autoLink && isValidElement(firstChildren)) {
|
||||
if (this.prop && autoLink && isValidElement(firstChildren)) {
|
||||
const originalEvents = getEvents(firstChildren);
|
||||
const originalBlur = originalEvents.blur;
|
||||
const originalChange = originalEvents.change;
|
||||
const originalBlur = originalEvents.onBlur;
|
||||
const originalChange = originalEvents.onChange;
|
||||
firstChildren = cloneElement(firstChildren, {
|
||||
on: {
|
||||
blur: (...args) => {
|
||||
originalBlur && originalBlur(...args);
|
||||
this.onFieldBlur();
|
||||
},
|
||||
change: (...args) => {
|
||||
if (Array.isArray(originalChange)) {
|
||||
for (let i = 0, l = originalChange.length; i < l; i++) {
|
||||
originalChange[i](...args);
|
||||
}
|
||||
} else if (originalChange) {
|
||||
originalChange(...args);
|
||||
onBlur: (...args) => {
|
||||
originalBlur && originalBlur(...args);
|
||||
this.onFieldBlur();
|
||||
},
|
||||
onChange: (...args) => {
|
||||
if (Array.isArray(originalChange)) {
|
||||
for (let i = 0, l = originalChange.length; i < l; i++) {
|
||||
originalChange[i](...args);
|
||||
}
|
||||
this.onFieldChange();
|
||||
},
|
||||
} else if (originalChange) {
|
||||
originalChange(...args);
|
||||
}
|
||||
this.onFieldChange();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,20 +1,12 @@
|
|||
import Vue from 'vue';
|
||||
import Form from './Form';
|
||||
import ref from 'vue-ref';
|
||||
import FormDecoratorDirective from '../_util/FormDecoratorDirective';
|
||||
import Base from '../base';
|
||||
|
||||
Vue.use(ref, { name: 'ant-ref' });
|
||||
Vue.use(FormDecoratorDirective);
|
||||
|
||||
export { FormProps, ValidationRule } from './Form';
|
||||
export { FormItemProps } from './FormItem';
|
||||
|
||||
/* istanbul ignore next */
|
||||
Form.install = function(Vue) {
|
||||
Vue.use(Base);
|
||||
Vue.component(Form.name, Form);
|
||||
Vue.component(Form.Item.name, Form.Item);
|
||||
Form.install = function(app) {
|
||||
app.component(Form.name, Form);
|
||||
app.component(Form.Item.name, Form.Item);
|
||||
};
|
||||
|
||||
export default Form;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { provide, inject, Transition } from 'vue';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import classNames from 'classnames';
|
||||
import find from 'lodash/find';
|
||||
|
@ -7,11 +8,12 @@ import warning from '../_util/warning';
|
|||
import { FIELD_META_PROP, FIELD_DATA_PROP } from './constants';
|
||||
import {
|
||||
initDefaultProps,
|
||||
getComponentFromProp,
|
||||
filterEmpty,
|
||||
getComponent,
|
||||
getSlotOptions,
|
||||
isValidElement,
|
||||
getAllChildren,
|
||||
findDOMNode,
|
||||
getSlot,
|
||||
} from '../_util/props-util';
|
||||
import getTransitionProps from '../_util/getTransitionProps';
|
||||
import BaseMixin from '../_util/BaseMixin';
|
||||
|
@ -73,23 +75,21 @@ function comeFromSlot(vnodes = [], itemVnode) {
|
|||
|
||||
export default {
|
||||
name: 'AFormItem',
|
||||
__ANT_FORM_ITEM: true,
|
||||
mixins: [BaseMixin],
|
||||
inheritAttrs: false,
|
||||
__ANT_FORM_ITEM: true,
|
||||
props: initDefaultProps(FormItemProps, {
|
||||
hasFeedback: false,
|
||||
}),
|
||||
provide() {
|
||||
setup() {
|
||||
return {
|
||||
isFormItemChildren: true,
|
||||
isFormItemChildren: inject('isFormItemChildren', false),
|
||||
FormContext: inject('FormContext', {}),
|
||||
decoratorFormProps: inject('decoratorFormProps', {}),
|
||||
collectFormItemContext: inject('collectFormItemContext', noop),
|
||||
configProvider: inject('configProvider', ConfigConsumerProps),
|
||||
};
|
||||
},
|
||||
inject: {
|
||||
isFormItemChildren: { default: false },
|
||||
FormContext: { default: () => ({}) },
|
||||
decoratorFormProps: { default: () => ({}) },
|
||||
collectFormItemContext: { default: () => noop },
|
||||
configProvider: { default: () => ConfigConsumerProps },
|
||||
},
|
||||
data() {
|
||||
return { helpShow: false };
|
||||
},
|
||||
|
@ -99,6 +99,7 @@ export default {
|
|||
},
|
||||
},
|
||||
created() {
|
||||
provide('isFormItemChildren', true);
|
||||
this.collectContext();
|
||||
},
|
||||
beforeUpdate() {
|
||||
|
@ -145,7 +146,7 @@ export default {
|
|||
}
|
||||
},
|
||||
getHelpMessage() {
|
||||
const help = getComponentFromProp(this, 'help');
|
||||
const help = getComponent(this, 'help');
|
||||
const onlyControl = this.getOnlyControl();
|
||||
if (help === undefined && onlyControl) {
|
||||
const errors = this.getField().errors;
|
||||
|
@ -177,15 +178,15 @@ export default {
|
|||
}
|
||||
|
||||
const child = childrenArray[i];
|
||||
if (!child.tag && child.text.trim() === '') {
|
||||
continue;
|
||||
}
|
||||
// if (!child.tag && child.text.trim() === '') {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
if (getSlotOptions(child).__ANT_FORM_ITEM) {
|
||||
if (typeof child.type === 'object' && child.type.__ANT_FORM_ITEM) {
|
||||
continue;
|
||||
}
|
||||
const children = getAllChildren(child);
|
||||
const attrs = (child.data && child.data.attrs) || {};
|
||||
const attrs = child.props || {};
|
||||
if (FIELD_META_PROP in attrs) {
|
||||
// And means FIELD_DATA_PROP in child.props, too.
|
||||
controls.push(child);
|
||||
|
@ -207,6 +208,7 @@ export default {
|
|||
if (!child) {
|
||||
return undefined;
|
||||
}
|
||||
debugger;
|
||||
if (child.data) {
|
||||
data = child.data;
|
||||
} else if (child.$vnode && child.$vnode.data) {
|
||||
|
@ -253,7 +255,7 @@ export default {
|
|||
if (!id) {
|
||||
return;
|
||||
}
|
||||
const formItemNode = this.$el;
|
||||
const formItemNode = findDOMNode(this);
|
||||
const control = formItemNode.querySelector(`[id="${id}"]`);
|
||||
if (control && control.focus) {
|
||||
control.focus();
|
||||
|
@ -296,18 +298,18 @@ export default {
|
|||
this.helpShow = !!children;
|
||||
}
|
||||
const transitionProps = getTransitionProps('show-help', {
|
||||
afterEnter: () => this.onHelpAnimEnd('help', true),
|
||||
afterLeave: () => this.onHelpAnimEnd('help', false),
|
||||
onAfterEnter: () => this.onHelpAnimEnd('help', true),
|
||||
onAfterLeave: () => this.onHelpAnimEnd('help', false),
|
||||
});
|
||||
return (
|
||||
<transition {...transitionProps} key="help">
|
||||
<Transition {...transitionProps} key="help">
|
||||
{children}
|
||||
</transition>
|
||||
</Transition>
|
||||
);
|
||||
},
|
||||
|
||||
renderExtra(prefixCls) {
|
||||
const extra = getComponentFromProp(this, 'extra');
|
||||
const extra = getComponent(this, 'extra');
|
||||
return extra ? <div class={`${prefixCls}-extra`}>{extra}</div> : null;
|
||||
},
|
||||
|
||||
|
@ -353,15 +355,14 @@ export default {
|
|||
const { wrapperCol: contextWrapperCol } = this.isFormItemChildren ? {} : this.FormContext;
|
||||
const { wrapperCol } = this;
|
||||
const mergedWrapperCol = wrapperCol || contextWrapperCol || {};
|
||||
const { style, id, on, ...restProps } = mergedWrapperCol;
|
||||
const { style, id, ...restProps } = mergedWrapperCol;
|
||||
const className = classNames(`${prefixCls}-item-control-wrapper`, mergedWrapperCol.class);
|
||||
const colProps = {
|
||||
props: restProps,
|
||||
...restProps,
|
||||
class: className,
|
||||
key: 'wrapper',
|
||||
style,
|
||||
id,
|
||||
on,
|
||||
};
|
||||
return <Col {...colProps}>{children}</Col>;
|
||||
},
|
||||
|
@ -374,7 +375,7 @@ export default {
|
|||
colon: contextColon,
|
||||
} = this.FormContext;
|
||||
const { labelAlign, labelCol, colon, id, htmlFor } = this;
|
||||
const label = getComponentFromProp(this, 'label');
|
||||
const label = getComponent(this, 'label');
|
||||
const required = this.isRequired();
|
||||
const mergedLabelCol = labelCol || contextLabelCol || {};
|
||||
|
||||
|
@ -389,7 +390,6 @@ export default {
|
|||
class: labelColClass,
|
||||
style: labelColStyle,
|
||||
id: labelColId,
|
||||
on,
|
||||
...restProps
|
||||
} = mergedLabelCol;
|
||||
let labelChildren = label;
|
||||
|
@ -406,12 +406,11 @@ export default {
|
|||
[`${prefixCls}-item-no-colon`]: !computedColon,
|
||||
});
|
||||
const colProps = {
|
||||
props: restProps,
|
||||
...restProps,
|
||||
class: labelColClassName,
|
||||
key: 'label',
|
||||
style: labelColStyle,
|
||||
id: labelColId,
|
||||
on,
|
||||
};
|
||||
|
||||
return label ? (
|
||||
|
@ -443,16 +442,18 @@ export default {
|
|||
},
|
||||
renderFormItem() {
|
||||
const { prefixCls: customizePrefixCls } = this.$props;
|
||||
const { class: className, ...restProps } = this.$attrs;
|
||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||
const prefixCls = getPrefixCls('form', customizePrefixCls);
|
||||
const children = this.renderChildren(prefixCls);
|
||||
const itemClassName = {
|
||||
[className]: true,
|
||||
[`${prefixCls}-item`]: true,
|
||||
[`${prefixCls}-item-with-help`]: this.helpShow,
|
||||
};
|
||||
|
||||
return (
|
||||
<Row class={classNames(itemClassName)} key="row">
|
||||
<Row class={classNames(itemClassName)} key="row" {...restProps}>
|
||||
{children}
|
||||
</Row>
|
||||
);
|
||||
|
@ -497,14 +498,8 @@ export default {
|
|||
},
|
||||
|
||||
render() {
|
||||
const {
|
||||
$slots,
|
||||
decoratorFormProps,
|
||||
fieldDecoratorId,
|
||||
fieldDecoratorOptions = {},
|
||||
FormContext,
|
||||
} = this;
|
||||
let child = filterEmpty($slots.default || []);
|
||||
const { decoratorFormProps, fieldDecoratorId, fieldDecoratorOptions = {}, FormContext } = this;
|
||||
let child = getSlot(this);
|
||||
if (decoratorFormProps.form && fieldDecoratorId && child.length) {
|
||||
const getFieldDecorator = decoratorFormProps.form.getFieldDecorator;
|
||||
child[0] = getFieldDecorator(fieldDecoratorId, fieldDecoratorOptions, this)(child[0]);
|
||||
|
|
|
@ -17,6 +17,9 @@ import {
|
|||
Tooltip,
|
||||
Col,
|
||||
Row,
|
||||
FormModel,
|
||||
Switch,
|
||||
Checkbox,
|
||||
notification,
|
||||
message,
|
||||
} from 'ant-design-vue';
|
||||
|
@ -49,6 +52,9 @@ app
|
|||
.use(Col)
|
||||
.use(Row)
|
||||
.use(Radio)
|
||||
.use(Switch)
|
||||
.use(Checkbox)
|
||||
.use(InputNumber)
|
||||
.use(AutoComplete)
|
||||
.use(FormModel)
|
||||
.mount('#app');
|
||||
|
|
Loading…
Reference in New Issue