diff --git a/components/form/FormItem.jsx b/components/form/FormItem.jsx index 4041f9d06..cff6fa92f 100644 --- a/components/form/FormItem.jsx +++ b/components/form/FormItem.jsx @@ -97,6 +97,9 @@ export default { getChildAttr (prop) { const child = this.getOnlyControl() let data = {} + if (!child) { + return undefined + } if (child.data) { data = child.data } else if (child.$vnode && child.$vnode.data) { diff --git a/components/form/demo/coordinated.md b/components/form/demo/coordinated.md new file mode 100644 index 000000000..f57276ca2 --- /dev/null +++ b/components/form/demo/coordinated.md @@ -0,0 +1,82 @@ + +#### 表单联动 +使用 `setFieldsValue` 来动态设置其他控件的值。 + + + +#### Coordinated Controls +Use `setFieldsValue` to set other control's value programmaticly. + + +```html + +``` + + + diff --git a/components/form/demo/customized-form-controls.md b/components/form/demo/customized-form-controls.md new file mode 100644 index 000000000..aec358d5c --- /dev/null +++ b/components/form/demo/customized-form-controls.md @@ -0,0 +1,129 @@ + +#### 自定义表单控件 +自定义或第三方的表单控件,也可以与 Form 组件一起使用。只要该组件遵循以下的约定: +> * 提供受控属性 `value` 或其它与 [`valuePropName`](/ant-design/components/form-cn/#getFieldDecorator(id,-options)-参数) 的值同名的属性。 +> * 提供 `onChange` 事件或 [`trigger`](/ant-design/components/form-cn/#getFieldDecorator(id,-options)-参数) 的值同名的事件。 +> * 不能是函数式组件。 + + + +#### Customized Form Controls +Customized or third-party form controls can be used in Form, too. Controls must follow these conventions: +> * It has a controlled property `value` or other name which is equal to the value of [`valuePropName`](/ant-design/components/form/#getFieldDecorator(id,-options)-parameters). +> * It has event `onChange` or an event which name is equal to the value of [`trigger`](/ant-design/components/form/#getFieldDecorator(id,-options)-parameters). +> * It must be a class component. + + +```html + +``` + + + diff --git a/components/form/demo/dynamic-form-item.md b/components/form/demo/dynamic-form-item.md new file mode 100644 index 000000000..91d6a5f40 --- /dev/null +++ b/components/form/demo/dynamic-form-item.md @@ -0,0 +1,144 @@ + +#### 动态增减表单项 +动态增加、减少表单项。 + + + +#### Dynamic Form Item +Add or remove form items dynamically. + + +```html + + + +``` + + + diff --git a/components/form/demo/dynamic-rule.md b/components/form/demo/dynamic-rule.md new file mode 100644 index 000000000..38648fe7b --- /dev/null +++ b/components/form/demo/dynamic-rule.md @@ -0,0 +1,94 @@ + +#### 动态校验规则 +根据不同情况执行不同的校验规则。 + + + +#### Dynamic Rules +Perform different check rules according to different situations. + + +```html + +``` + + + diff --git a/components/form/demo/form-in-modal.md b/components/form/demo/form-in-modal.md new file mode 100644 index 000000000..bade491cc --- /dev/null +++ b/components/form/demo/form-in-modal.md @@ -0,0 +1,105 @@ + +#### 弹出层中的新建表单 +当用户访问一个展示了某个列表的页面,想新建一项但又不想跳转页面时,可以用 Modal 弹出一个表单,用户填写必要信息后创建新的项。 + + + +#### Form in Modal to Create +When user visit a page with a list of items, and want to create a new item. The page can popup a form in Modal, then let user fill in the form to create an item. + + +```html + +``` + + + diff --git a/components/form/demo/global-state.md b/components/form/demo/global-state.md new file mode 100644 index 000000000..b3d5a1f47 --- /dev/null +++ b/components/form/demo/global-state.md @@ -0,0 +1,92 @@ + +#### 表单数据存储于上层组件 +通过使用 `onFieldsChange` 与 `mapPropsToFields`,可以把表单的数据存储到上层组件。 +**注意:** +`mapPropsToFields` 里面返回的表单域数据必须使用 `Form.createFormField` 包装。 +上层组件传递的属性,必须在`Form.create({ props: ...})`的props中声明。 + + + +#### Store Form Data into Upper Component +We can store form data into upper component. +**Note:** +You must wrap field data with `Form.createFormField` in `mapPropsToFields`. +The properties passed by the upper component must be declared in the props of `Form.create({ props: ...})`. + + +```html + + +``` + + + diff --git a/components/form/demo/horizontal-login.md b/components/form/demo/horizontal-login.md new file mode 100644 index 000000000..f24b1add9 --- /dev/null +++ b/components/form/demo/horizontal-login.md @@ -0,0 +1,82 @@ + +#### 水平登录栏 +水平登录栏,常用在顶部导航栏中。 + + + +#### Horizontal Login Form +Horizontal login form is often used in navigation bar. + + +```html + +``` + + + diff --git a/components/form/demo/layout.md b/components/form/demo/layout.md new file mode 100644 index 000000000..174c860f4 --- /dev/null +++ b/components/form/demo/layout.md @@ -0,0 +1,81 @@ + +#### 表单布局 +表单有三种布局。 + + + +#### Form Layout +There are three layout for form: `horizontal`, `vertical`, `inline`. + + +```html + + + +``` + + + diff --git a/components/form/demo/test.vue b/components/form/demo/test.vue index decc789f7..026703bca 100644 --- a/components/form/demo/test.vue +++ b/components/form/demo/test.vue @@ -1,64 +1,67 @@ - - \ No newline at end of file + diff --git a/components/vc-form/src/createBaseForm.jsx b/components/vc-form/src/createBaseForm.jsx index eacd387f4..107985c61 100644 --- a/components/vc-form/src/createBaseForm.jsx +++ b/components/vc-form/src/createBaseForm.jsx @@ -7,7 +7,7 @@ import createFieldsStore from './createFieldsStore' import { cloneElement } from '../../_util/vnode' import BaseMixin from '../../_util/BaseMixin' import { getOptionProps, getEvents } from '../../_util/props-util' -// import PropTypes from '../../_util/vue-types' +import PropTypes from '../../_util/vue-types' import { argumentContainer, @@ -34,17 +34,24 @@ function createBaseForm (option = {}, mixins = []) { fieldMetaProp, fieldDataProp, formPropName = 'form', - // @deprecated - withRef, + props = {}, } = option return function decorate (WrappedComponent) { + let formProps = {} + if (Array.isArray(props)) { + props.forEach((prop) => { + formProps[prop] = PropTypes.any + }) + } else { + formProps = props + } const Form = { mixins: [BaseMixin, ...mixins], - // props: { - // hideRequiredMark: PropTypes.bool, - // layout: PropTypes.string, - // }, + props: { + ...formProps, + wrappedComponentRef: PropTypes.func.def(() => {}), + }, data () { const fields = mapPropsToFields && mapPropsToFields(this.$props) this.fieldsStore = createFieldsStore(fields || {}) @@ -81,6 +88,9 @@ function createBaseForm (option = {}, mixins = []) { deep: true, }, }, + mounted () { + this.wrappedComponentRef(this.$refs.WrappedComponent) + }, methods: { onCollectCommon (name, action, args) { const fieldMeta = this.fieldsStore.getFieldMeta(name) @@ -554,17 +564,22 @@ function createBaseForm (option = {}, mixins = []) { ...props, }), on: $listeners, - } - if (withRef) { - wrappedComponentProps.ref = 'wrappedComponent' + ref: 'WrappedComponent', } return }, } - if (!(WrappedComponent.props && formPropName in WrappedComponent.props)) { - WrappedComponent.props = { - ...WrappedComponent.props, - [formPropName]: Object, + if (Array.isArray(WrappedComponent.props)) { + const newProps = {} + WrappedComponent.props.forEach((prop) => { + newProps[prop] = PropTypes.any + }) + newProps[formPropName] = Object + WrappedComponent.props = newProps + } else { + WrappedComponent.props = WrappedComponent.props || {} + if (!(formPropName in WrappedComponent.props)) { + WrappedComponent.props[formPropName] = Object } } return argumentContainer(Form, WrappedComponent)