Skip to content

Commit 868ee1e

Browse files
committed
feat: support form template
1 parent 090f9cb commit 868ee1e

File tree

6 files changed

+175
-171
lines changed

6 files changed

+175
-171
lines changed

components/form/Form.jsx

+29-25
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ export const FormProps = {
5757
// onSubmit: React.FormEventHandler<any>;
5858
prefixCls: PropTypes.string,
5959
hideRequiredMark: PropTypes.bool,
60-
formRef: PropTypes.func,
60+
autoFormCreate: PropTypes.func,
61+
options: PropTypes.object,
6162
}
6263

6364
export const ValidationRule = {
@@ -144,23 +145,6 @@ export default {
144145
fieldDataProp: FIELD_DATA_PROP,
145146
})
146147
},
147-
148-
// constructor (props) {
149-
// super(props)
150-
151-
// warning(!props.form, 'It is unnecessary to pass `form` to `Form` after [email protected].')
152-
// }
153-
154-
// shouldComponentUpdate(...args) {
155-
// return PureRenderMixin.shouldComponentUpdate.apply(this, args);
156-
// }
157-
158-
// getChildContext () {
159-
// const { layout } = this.props
160-
// return {
161-
// vertical: layout === 'vertical',
162-
// }
163-
// },
164148
provide () {
165149
return {
166150
FormProps: this.$props,
@@ -179,7 +163,7 @@ export default {
179163

180164
render () {
181165
const {
182-
prefixCls, hideRequiredMark, layout, onSubmit, $slots, formRef,
166+
prefixCls, hideRequiredMark, layout, onSubmit, $slots, autoFormCreate, options = {},
183167
} = this
184168

185169
const formClassName = classNames(prefixCls, {
@@ -188,25 +172,45 @@ export default {
188172
[`${prefixCls}-inline`]: layout === 'inline',
189173
[`${prefixCls}-hide-required-mark`]: hideRequiredMark,
190174
})
191-
if (formRef) {
192-
const NewForm = createDOMForm({
175+
if (autoFormCreate) {
176+
const saveFormRef = (ref) => {
177+
this.domForm = ref
178+
}
179+
const DomForm = this.DomForm || createDOMForm({
193180
fieldNameProp: 'id',
181+
...options,
194182
fieldMetaProp: FIELD_META_PROP,
195183
fieldDataProp: FIELD_DATA_PROP,
184+
templateContext: this.$parent,
196185
})({
197186
provide () {
198187
return {
199-
NewFormProps: this.$props,
188+
decoratorFormProps: this.$props,
189+
}
190+
},
191+
data () {
192+
return {
193+
children: $slots.default,
194+
formClassName: formClassName,
195+
submit: onSubmit,
200196
}
201197
},
202198
mounted () {
203-
formRef(this.form)
199+
autoFormCreate(this.form)
204200
},
205201
render () {
206-
return <form onSubmit={onSubmit} class={formClassName}>{$slots.default}</form>
202+
const { children, formClassName, submit } = this
203+
return <form onSubmit={submit} class={formClassName}>{children}</form>
207204
},
208205
})
209-
return <NewForm />
206+
if (this.domForm) {
207+
this.domForm.children = $slots.default
208+
this.domForm.submit = onSubmit
209+
this.domForm.formClassName = formClassName
210+
}
211+
this.DomForm = DomForm
212+
213+
return <DomForm wrappedComponentRef={(inst) => saveFormRef(inst)}/>
210214
}
211215

212216
return <form onSubmit={onSubmit} class={formClassName}>{$slots.default}</form>

components/form/FormItem.jsx

+9-9
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Row from '../grid/Row'
55
import Col, { ColProps } from '../grid/Col'
66
import warning from '../_util/warning'
77
import { FIELD_META_PROP, FIELD_DATA_PROP } from './constants'
8-
import { initDefaultProps, getComponentFromProp, filterEmpty, getSlotOptions, getSlots } from '../_util/props-util'
8+
import { initDefaultProps, getComponentFromProp, filterEmpty, getSlotOptions, getSlots, isEmptyElement } from '../_util/props-util'
99
import getTransitionProps from '../_util/getTransitionProps'
1010
import BaseMixin from '../_util/BaseMixin'
1111
export const FormItemProps = {
@@ -35,14 +35,14 @@ export default {
3535
}),
3636
inject: {
3737
FormProps: { default: {}},
38-
NewFormProps: { default: {}},
38+
decoratorFormProps: { default: {}},
3939
},
4040
data () {
4141
return { helpShow: false }
4242
},
4343
mounted () {
4444
warning(
45-
this.getControls(this.$slots.default, true).length <= 1,
45+
this.getControls(this.slotDefault, true).length <= 1,
4646
'`Form.Item` cannot generate `validateStatus` and `help` automatically, ' +
4747
'while there are more than one `getFieldDecorator` in it.',
4848
)
@@ -306,10 +306,10 @@ export default {
306306
) : null
307307
},
308308
renderChildren () {
309-
// const { $slots, FormProps, NewFormProps, prop } = this
309+
// const { $slots, FormProps, decoratorFormProps, prop } = this
310310
// const child = filterEmpty($slots.default || [])
311-
// if (NewFormProps.form && prop && child.length) {
312-
// const getFieldDecorator = NewFormProps.form.getFieldDecorator
311+
// if (decoratorFormProps.form && prop && child.length) {
312+
// const getFieldDecorator = decoratorFormProps.form.getFieldDecorator
313313
// const rules = FormProps.rules[prop] || []
314314
// child[0] = getFieldDecorator(prop, {
315315
// rules,
@@ -344,10 +344,10 @@ export default {
344344
},
345345

346346
render () {
347-
const { $slots, NewFormProps, fieldDecoratorId, fieldDecoratorOptions = {}} = this
347+
const { $slots, decoratorFormProps, fieldDecoratorId, fieldDecoratorOptions = {}} = this
348348
const child = filterEmpty($slots.default || [])
349-
if (NewFormProps.form && fieldDecoratorId && child.length) {
350-
const getFieldDecorator = NewFormProps.form.getFieldDecorator
349+
if (decoratorFormProps.form && fieldDecoratorId && child.length) {
350+
const getFieldDecorator = decoratorFormProps.form.getFieldDecorator
351351
child[0] = getFieldDecorator(fieldDecoratorId, fieldDecoratorOptions)(child[0])
352352
}
353353
this.slotDefault = child

components/form/demo/coordinated.vue

+43-48
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,49 @@ Use `setFieldsValue` to set other control's value programmaticly.
99
</us>
1010

1111

12-
<script>
13-
import { Form } from 'vue-antd-ui'
12+
<template>
13+
<a-form @submit="handleSubmit" :autoFormCreate="(form)=>{this.form = form}">
14+
<a-form-item
15+
label='Note'
16+
:labelCol="{ span: 5 }"
17+
:wrapperCol="{ span: 12 }"
18+
fieldDecoratorId="note"
19+
:fieldDecoratorOptions="{rules: [{ required: true, message: 'Please input your note!' }]}"
20+
>
21+
<a-input />
22+
</a-form-item>
23+
<a-form-item
24+
label='Gender'
25+
:labelCol="{ span: 5 }"
26+
:wrapperCol="{ span: 12 }"
27+
fieldDecoratorId="gender"
28+
:fieldDecoratorOptions="{rules: [{ required: true, message: 'Please select your gender!' }]}"
29+
>
30+
<a-select
31+
placeholder='Select a option and change input text above'
32+
@change="this.handleSelectChange"
33+
>
34+
<a-select-option value='male'>male</a-select-option>
35+
<a-select-option value='female'>female</a-select-option>
36+
</a-select>
37+
</a-form-item>
38+
<a-form-item
39+
:wrapperCol="{ span: 12, offset: 5 }"
40+
>
41+
<a-button type='primary' htmlType='submit'>
42+
Submit
43+
</a-button>
44+
</a-form-item>
45+
</a-form>
46+
</template>
1447

15-
const CoordinatedForm = {
48+
<script>
49+
export default {
50+
data () {
51+
return {
52+
formLayout: 'horizontal',
53+
}
54+
},
1655
methods: {
1756
handleSubmit (e) {
1857
e.preventDefault()
@@ -29,54 +68,10 @@ const CoordinatedForm = {
2968
})
3069
},
3170
},
32-
33-
render () {
34-
const { getFieldDecorator } = this.form
35-
return (
36-
<a-form onSubmit={this.handleSubmit}>
37-
<a-form-item
38-
label='Note'
39-
labelCol={{ span: 5 }}
40-
wrapperCol={{ span: 12 }}
41-
>
42-
{getFieldDecorator('note', {
43-
rules: [{ required: true, message: 'Please input your note!' }],
44-
})(
45-
<a-input />
46-
)}
47-
</a-form-item>
48-
<a-form-item
49-
label='Gender'
50-
labelCol={{ span: 5 }}
51-
wrapperCol={{ span: 12 }}
52-
>
53-
{getFieldDecorator('gender', {
54-
rules: [{ required: true, message: 'Please select your gender!' }],
55-
})(
56-
<a-select
57-
placeholder='Select a option and change input text above'
58-
onChange={this.handleSelectChange}
59-
>
60-
<a-select-option value='male'>male</a-select-option>
61-
<a-select-option value='female'>female</a-select-option>
62-
</a-select>
63-
)}
64-
</a-form-item>
65-
<a-form-item
66-
wrapperCol={{ span: 12, offset: 5 }}
67-
>
68-
<a-button type='primary' htmlType='submit'>
69-
Submit
70-
</a-button>
71-
</a-form-item>
72-
</a-form>
73-
)
74-
},
7571
}
76-
77-
export default Form.create()(CoordinatedForm)
7872
</script>
7973

8074

8175

8276

77+

components/form/demo/dynamic-rule.vue

+36-46
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,39 @@ Perform different check rules according to different situations.
99
</us>
1010

1111

12-
<script>
13-
import { Form } from 'vue-antd-ui'
12+
<template>
13+
<a-form :autoFormCreate="(form)=>{this.form = form}">
14+
<a-form-item
15+
:formItemLayout="formItemLayout"
16+
label='Name'
17+
fieldDecoratorId="username"
18+
:fieldDecoratorOptions="{rules: [{ required: true, message: 'Please input your name' }]}"
19+
>
20+
<a-input placeholder='Please input your name' />
21+
</a-form-item>
22+
<a-form-item
23+
:formItemLayout="formItemLayout"
24+
label='Nickname'
25+
fieldDecoratorId="nickname"
26+
:fieldDecoratorOptions="{rules: [{ required: checkNick, message: 'Please input your nickname' }]}"
27+
>
28+
<a-input placeholder='Please input your nickname' />
29+
</a-form-item>
30+
<a-form-item :formTailLayout="formTailLayout">
31+
<a-checkbox
32+
:checked="checkNick"
33+
@change="handleChange"
34+
>
35+
Nickname is required
36+
</a-checkbox>
37+
</a-form-item>
38+
<a-form-item :formTailLayout="formTailLayout">
39+
<a-button type='primary' @click="check">Check</a-button>
40+
</a-form-item>
41+
</a-form>
42+
</template>
1443

44+
<script>
1545
const formItemLayout = {
1646
labelCol: { span: 4 },
1747
wrapperCol: { span: 8 },
@@ -20,10 +50,12 @@ const formTailLayout = {
2050
labelCol: { span: 4 },
2151
wrapperCol: { span: 8, offset: 4 },
2252
}
23-
const DynamicRule = {
53+
export default {
2454
data () {
2555
return {
2656
checkNick: false,
57+
formItemLayout,
58+
formTailLayout,
2759
}
2860
},
2961
methods: {
@@ -43,52 +75,10 @@ const DynamicRule = {
4375
})
4476
},
4577
},
46-
47-
render () {
48-
const { getFieldDecorator } = this.form
49-
return (
50-
<div>
51-
<a-form-item {...{ props: formItemLayout }} label='Name'>
52-
{getFieldDecorator('username', {
53-
rules: [{
54-
required: true,
55-
message: 'Please input your name',
56-
}],
57-
})(
58-
<a-input placeholder='Please input your name' />
59-
)}
60-
</a-form-item>
61-
<a-form-item {...{ props: formItemLayout }} label='Nickname'>
62-
{getFieldDecorator('nickname', {
63-
rules: [{
64-
required: this.checkNick,
65-
message: 'Please input your nickname',
66-
}],
67-
})(
68-
<a-input placeholder='Please input your nickname' />
69-
)}
70-
</a-form-item>
71-
<a-form-item {...{ props: formTailLayout }}>
72-
<a-checkbox
73-
value={this.checkNick}
74-
onChange={this.handleChange}
75-
>
76-
Nickname is required
77-
</a-checkbox>
78-
</a-form-item>
79-
<a-form-item {...{ props: formTailLayout }}>
80-
<a-button type='primary' onClick={this.check}>
81-
Check
82-
</a-button>
83-
</a-form-item>
84-
</div>
85-
)
86-
},
8778
}
88-
89-
export default Form.create()(DynamicRule)
9079
</script>
9180

9281

9382

9483

84+

0 commit comments

Comments
 (0)