基于antd 3.x 的自定义表单实现方案
问题
- 表单逻辑复杂需要大量自定义表单满足需求
- 表单字段过多嵌套过深
- 表单校验问题
解决办法:通过组合自定义表单组件实现复杂的表单的逻辑和校验功能
父级表单
- childFormItem
- getInstance
@Form.create()
@withRef
class Parent extends Component {
constructor(props) {
super(props);
this.childFormItem = null;
this.state = {
formValues: {}
};
}
componentWillUnMount(){
this.childFormItem = null;
}
render() {
const { formValues } = this.state
const { getFieldDecorator} = form;
return (
<div >
<FormItem>
{
getFieldDecorator(`formValue`, {
initialValue: formValues,
rules: [
{
required: true,
message: "请输入前提条件"
}
]
})(
<ChildFirmItem
getInstance={ins => this.childFormItem = ins}
onChange={this.handleChange.bind(this)}
/>
)
}
</FormItem>
</div>
);
}
// 校验
handleVerifyValue() {
// 校验并拼接返回值
return new Promise((resolve, reject) => {
this.props.form.validateFields(async (error, values) => {
if (error) return reject(error);
const [err, values] = await to(this.childFormItem.handleVerifyValue());
if (err) return reject(err);
return resolve(values)
})
})
}
// 更新value
handleChange() {
setTimeout(() => {
const value = this.props.form.getFieldsValue();
this.props.onChange(formValues);
});
}
}
自定义子组件
- @withRef
- handleChange
- handleVerifyValue
@Form.create()
@withRef
class Child extends Component {
constructor(props) {
super(props);
}
// 校验
handleVerifyValue() {
return new Promise((resolve, reject) => {
this.props.form.validateFields((error, values) => {
if (error) {
return reject(error)
} else {
return resolve(values)
}
})
})
}
//更新value
handleChange () {
setTimeout(() => {
const values = this.props.form.getFieldsValue();
this.props.onChange(values);
});
}
render() {
const { form, value } = this.props
const { getFieldDecorator } = form
return (
<FormItem>
{
getFieldDecorator("dtFormat", {
initialValue: value.dtFormat || void 0",
rules: [
{
required: true,
message: "请输入"
}
]
})(
<Input
type="text"
placeholder={"请输入"}
onChange={this.handleChange.bind(this)}
/>
)
}
</FormItem>
)
}
}
@withRef
export default (WrappedComponent) => {
return class withRef extends Component {
static displayName = `withRef(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})`;
render() {
const props = { ...this.props };
// 在这里把getInstance赋值给ref,
props.ref = (el) => {
this.props.getInstance && this.props.getInstance(el);
this.props.ref && this.props.ref(el);
}
return (
<WrappedComponent {...props} />
);
}
};
};