feat: update form

This commit is contained in:
wangxueliang 2019-04-20 14:19:13 +08:00
parent 300fc9a2bc
commit 3a2977a2ed
17 changed files with 55 additions and 43 deletions

View File

@ -8,6 +8,7 @@ import createFormField from '../vc-form/src/createFormField';
import FormItem from './FormItem';
import { FIELD_META_PROP, FIELD_DATA_PROP } from './constants';
import { initDefaultProps } from '../_util/props-util';
import { ConfigConsumerProps } from '../config-provider';
export const FormCreateOption = {
onFieldsChange: PropTypes.func,
@ -15,6 +16,7 @@ export const FormCreateOption = {
mapPropsToFields: PropTypes.func,
validateMessages: PropTypes.any,
withRef: PropTypes.bool,
name: PropTypes.string,
};
// function create
@ -119,15 +121,11 @@ export const ValidationRule = {
const Form = {
name: 'AForm',
props: initDefaultProps(FormProps, {
prefixCls: 'ant-form',
layout: 'horizontal',
hideRequiredMark: false,
}),
Item: FormItem,
createFormField: createFormField,
create: (options = {}) => {
return createDOMForm({
fieldNameProp: 'id',
@ -166,6 +164,9 @@ const Form = {
: () => {},
};
},
inject: {
configProvider: { default: () => ({}) },
},
watch: {
form() {
this.$forceUpdate();
@ -196,7 +197,7 @@ const Form = {
render() {
const {
prefixCls,
prefixCls: customizePrefixCls,
hideRequiredMark,
layout,
onSubmit,
@ -204,6 +205,8 @@ const Form = {
autoFormCreate,
options = {},
} = this;
const getPrefixCls = this.configProvider.getPrefixCls || ConfigConsumerProps.getPrefixCls;
const prefixCls = getPrefixCls('form', customizePrefixCls);
const formClassName = classNames(prefixCls, {
[`${prefixCls}-horizontal`]: layout === 'horizontal',

View File

@ -18,6 +18,7 @@ import getTransitionProps from '../_util/getTransitionProps';
import BaseMixin from '../_util/BaseMixin';
import { cloneElement, cloneVNodes } from '../_util/vnode';
import Icon from '../icon';
import { ConfigConsumerProps } from '../config-provider';
function noop() {}
export const FormItemProps = {
@ -65,6 +66,7 @@ export default {
FormProps: { default: () => ({}) },
decoratorFormProps: { default: () => ({}) },
collectFormItemContext: { default: () => noop },
configProvider: { default: () => ({}) },
},
data() {
return { helpShow: false };
@ -197,8 +199,7 @@ export default {
}
},
renderHelp() {
const prefixCls = this.prefixCls;
renderHelp(prefixCls) {
const help = this.getHelpMessage();
const children = help ? (
<div class={`${prefixCls}-explain`} key="help">
@ -219,8 +220,7 @@ export default {
);
},
renderExtra() {
const { prefixCls } = this;
renderExtra(prefixCls) {
const extra = getComponentFromProp(this, 'extra');
return extra ? <div class={`${prefixCls}-extra`}>{extra}</div> : null;
},
@ -244,7 +244,7 @@ export default {
return '';
},
renderValidateWrapper(c1, c2, c3) {
renderValidateWrapper(prefixCls, c1, c2, c3) {
const props = this.$props;
const onlyControl = this.getOnlyControl;
const validateStatus =
@ -252,9 +252,9 @@ export default {
? this.getValidateStatus()
: props.validateStatus;
let classes = `${props.prefixCls}-item-control`;
let classes = `${prefixCls}-item-control`;
if (validateStatus) {
classes = classNames(`${props.prefixCls}-item-control`, {
classes = classNames(`${prefixCls}-item-control`, {
'has-feedback': props.hasFeedback || validateStatus === 'validating',
'has-success': validateStatus === 'success',
'has-warning': validateStatus === 'warning',
@ -282,13 +282,13 @@ export default {
}
const icon =
props.hasFeedback && iconType ? (
<span class={`${props.prefixCls}-item-children-icon`}>
<span class={`${prefixCls}-item-children-icon`}>
<Icon type={iconType} theme={iconType === 'loading' ? 'outlined' : 'filled'} />
</span>
) : null;
return (
<div class={classes}>
<span class={`${props.prefixCls}-item-children`}>
<span class={`${prefixCls}-item-children`}>
{c1}
{icon}
</span>
@ -298,8 +298,8 @@ export default {
);
},
renderWrapper(children) {
const { prefixCls, wrapperCol = {} } = this;
renderWrapper(prefixCls, children) {
const { wrapperCol = {} } = this;
const { class: cls, style, id, on, ...restProps } = wrapperCol;
const className = classNames(`${prefixCls}-item-control-wrapper`, cls);
const colProps = {
@ -353,8 +353,8 @@ export default {
}
},
renderLabel() {
const { prefixCls, labelCol = {}, colon, id } = this;
renderLabel(prefixCls) {
const { labelCol = {}, colon, id } = this;
const label = getComponentFromProp(this, 'label');
const required = this.isRequired();
const {
@ -398,21 +398,29 @@ export default {
</Col>
) : null;
},
renderChildren() {
renderChildren(prefixCls) {
return [
this.renderLabel(),
this.renderLabel(prefixCls),
this.renderWrapper(
this.renderValidateWrapper(this.slotDefault, this.renderHelp(), this.renderExtra()),
prefixCls,
this.renderValidateWrapper(
prefixCls,
this.slotDefault,
this.renderHelp(prefixCls),
this.renderExtra(prefixCls)
),
),
];
},
renderFormItem(children) {
const props = this.$props;
const prefixCls = props.prefixCls;
renderFormItem() {
const { prefixCls: customizePrefixCls, colon } = this.$props;
const getPrefixCls = this.configProvider.getPrefixCls || ConfigConsumerProps.getPrefixCls;
const prefixCls = getPrefixCls('form', customizePrefixCls);
const children = this.renderChildren(prefixCls);
const itemClassName = {
[`${prefixCls}-item`]: true,
[`${prefixCls}-item-with-help`]: this.helpShow,
[`${prefixCls}-item-no-colon`]: !props.colon,
[`${prefixCls}-item-no-colon`]: !colon,
};
return <Row class={classNames(itemClassName)}>{children}</Row>;
@ -478,8 +486,6 @@ export default {
} else {
this.slotDefault = child;
}
const children = this.renderChildren();
return this.renderFormItem(children);
return this.renderFormItem();
},
};

View File

@ -77,7 +77,7 @@ export default {
data () {
return {
expand: false,
form: this.$form.createForm(this),
form: this.$form.createForm(this, { name: 'advanced_search' }),
};
},
computed: {

View File

@ -65,7 +65,7 @@ export default {
data () {
return {
formLayout: 'horizontal',
form: this.$form.createForm(this),
form: this.$form.createForm(this, { name: 'coordinated' }),
};
},
methods: {

View File

@ -111,7 +111,7 @@ export default {
PriceInput,
},
beforeCreate () {
this.form = this.$form.createForm(this);
this.form = this.$form.createForm(this, { name: 'customized_form_controls' });
},
methods: {
handleSubmit (e) {

View File

@ -89,7 +89,7 @@ export default {
};
},
beforeCreate () {
this.form = this.$form.createForm(this);
this.form = this.$form.createForm(this, { name: 'dynamic_form_item' });
this.form.getFieldDecorator('keys', { initialValue: [], preserve: true });
},
methods: {
@ -112,7 +112,7 @@ export default {
const { form } = this;
// can use data-binding to get
const keys = form.getFieldValue('keys');
const nextKeys = keys.concat(++id);
const nextKeys = keys.concat(id++);
// can use data-binding to set
// important! notify form to detect changes
form.setFieldsValue({

View File

@ -77,7 +77,7 @@ export default {
checkNick: false,
formItemLayout,
formTailLayout,
form: this.$form.createForm(this),
form: this.$form.createForm(this, { name: 'dynamic_rule' }),
};
},
methods: {

View File

@ -29,7 +29,7 @@ When user visit a page with a list of items, and want to create a new item. The
const CollectionCreateForm = {
props: ['visible'],
beforeCreate () {
this.form = this.$form.createForm(this);
this.form = this.$form.createForm(this, { name: 'form_in_modal' });
},
template: `
<a-modal

View File

@ -48,6 +48,7 @@ const CustomizedForm = {
`,
created () {
this.form = this.$form.createForm(this, {
name: 'global_state',
onFieldsChange: (_, changedFields) => {
this.$emit('change', changedFields);
},

View File

@ -72,7 +72,7 @@ export default {
data () {
return {
hasErrors,
form: this.$form.createForm(this),
form: this.$form.createForm(this, { name: 'horizontal_login' }),
};
},
mounted () {

View File

@ -82,7 +82,7 @@ Normal login form which can contain more elements.
export default {
beforeCreate () {
this.form = this.$form.createForm(this);
this.form = this.$form.createForm(this, { name: 'normal_login' });
},
methods: {
handleSubmit (e) {

View File

@ -248,7 +248,7 @@ export default {
};
},
beforeCreate () {
this.form = this.$form.createForm(this);
this.form = this.$form.createForm(this, { name: 'register' });
},
methods: {
handleSubmit (e) {

View File

@ -95,7 +95,7 @@ export default {
};
},
beforeCreate () {
this.form = this.$form.createForm(this);
this.form = this.$form.createForm(this, { name: 'time_related_controls' });
},
methods: {
handleSubmit (e) {

View File

@ -5,7 +5,7 @@
<us>
#### Other Form Controls
Demostration for validataion configuration for form controls which are not show in the above demos.
Demonstration of validation configuration for form controls which are not shown in the demos above.
</us>
@ -252,7 +252,7 @@ export default {
},
}),
beforeCreate () {
this.form = this.$form.createForm(this);
this.form = this.$form.createForm(this, { name: 'validate_other' });
},
methods: {
handleSubmit (e) {

View File

@ -77,7 +77,7 @@ We provide properties like `validateStatus` `help` `hasFeedback` to customize yo
validate-status="warning"
>
<a-input
id="warning"
id="warning2"
placeholder="Warning"
/>
</a-form-item>
@ -91,7 +91,7 @@ We provide properties like `validateStatus` `help` `hasFeedback` to customize yo
help="Should be combination of numbers & alphabets"
>
<a-input
id="error"
id="error2"
placeholder="unavailable choice"
/>
</a-form-item>

View File

@ -48,6 +48,7 @@ The following `options` are available:
| -------- | ----------- | ---- |
| props | Only supports the use of Form.create({})(CustomizedForm). declare props on form(和[like vue props]( https://vuejs.org/v2/api/#props)) | {} |
| mapPropsToFields | Convert props to field value(e.g. reading the values from Redux store). And you must mark returned fields with [`Form.createFormField`](#Form.createFormField). If you use `$form.createForm` to create a collector, you can map any data to the Field without being bound by the parent component. | (props) => Object{ fieldName: FormField { value } } |
| name | Set the id prefix of fields under form | - |
| validateMessages | Default validate message. And its format is similar with [newMessages](https://github.com/yiminghe/async-validator/blob/master/src/messages.js)'s returned value | Object { [nested.path]&#x3A; String } |
| onFieldsChange | Specify a function that will be called when the value a `Form.Item` gets changed. Usage example: saving the field's value to Redux store. | Function(props, fields) |
| onValuesChange | A handler while value of any field is changed | (props, values) => void |

View File

@ -46,6 +46,7 @@ export default {
| --- | --- | --- |
| props | 仅仅支持Form.create({})(CustomizedForm)的使用方式,父组件需要映射到表单项上的属性声明(和[vue组件props一致]( https://vuejs.org/v2/api/#props)) | {} |
| mapPropsToFields | 把父组件的属性映射到表单项上(如:把 Redux store 中的值读出),需要对返回值中的表单域数据用 [`Form.createFormField`](#Form.createFormField) 标记,如果使用$form.createForm创建收集器你可以将任何数据映射到Field中不受父组件约束 | (props) => ({ \[fieldName\]: FormField { value } }) |
| name | 设置表单域内字段 id 的前缀 | - |
| validateMessages | 默认校验信息,可用于把默认错误信息改为中文等,格式与 [newMessages](https://github.com/yiminghe/async-validator/blob/master/src/messages.js) 返回值一致 | Object { [nested.path]&#x3A; String } |
| onFieldsChange | 当 `Form.Item` 子节点的值发生改变时触发,可以把对应的值转存到 Redux store | Function(props, fields) |
| onValuesChange | 任一表单域的值发生改变时的回调 | (props, values) => void |