Reputation: 610
I have issue with setting initial values for antd dynamic form. Is there any way how to init values in dynamic for. It requires registered field using getFieldDecorator
. But for dynamic fields, that field is not registered before.
I am getting this error:
You cannot set field before registering it.
code: https://codesandbox.io/s/jnx3p1nz5
import React from "react";
import { Select, Icon, Button, Form, Input } from "antd";
const FormItem = Form.Item;
const TextArea = Input.TextArea;
const Option = Select.Option;
const SELECT = ['opt1', 'opt2'];
class TestForm extends React.Component {
state = {
listKeys: [0]
};
componentDidMount() {
const {
form: { setFieldsValue }
} = this.props;
// WORK
// setFieldsValue({
// name: 'test',
// });
// setFieldsValue({
// name: 'test',
// list: [
// {
// sub1: 'test1',
// sub2: 'test2',
// }
// ]
// });
// !!!!!!!!!!!! NOT WORK
// setFieldsValue({
// name: 'test',
// list: [
// {
// sub1: 'test1',
// sub2: 'opt2'
// },
// {
// sub1: 'test11',
// sub2: 'opt1'
// }
// ]
// });
setFieldsValue({
name: 'test',
list: [
{
sub1: 'test1',
sub2: 'opt2',
opt2sub: 'bla',
},
{
sub1: 'test11',
sub2: 'opt1'
},
{
sub1: 'test3',
sub2: 'opt2',
opt2sub: 'bla',
},
]
});
}
remove = k => {
const { listKeys } = this.state;
if (listKeys.length === 1) {
return;
}
this.setState({
listKeys: listKeys.filter(key => key !== k)
});
};
add = () => {
const { listKeys } = this.state;
this.setState({
listKeys: [...listKeys, listKeys.length]
});
};
render() {
const {
form: { getFieldDecorator, getFieldValue }
} = this.props;
const { listKeys } = this.state;
return (
<Form onSubmit={this.handleSubmit}>
<FormItem label="Name">
{getFieldDecorator("name")(<Input placeholder="name" />)}
</FormItem>
{listKeys.map((key, index) => {
const type = getFieldValue(`list[${key}].sub2`);
return (
<div key={key}>
<FormItem label="Sub1">
{getFieldDecorator(`list[${key}].sub1`)(
<Input placeholder="Sub1" />
)}
</FormItem>
<FormItem label="Sub2">
{getFieldDecorator(`list[${key}].sub2`,{
initialValue: 'opt1'
})(
<Select>
{SELECT.map(item => <Option key={item} value={item}>{item}</Option> )}
</Select>
)}
</FormItem>
{type === 'opt2' && (
<FormItem label="opt2sub">
{getFieldDecorator(`list[${key}].opt2sub`)(
<Input placeholder="opt2sub" />
)}
</FormItem>
)}
{index > 0 && (
<Icon
className="dynamic-delete-button"
type="minus-circle-o"
onClick={() => this.remove(key)}
/>
)}
</div>
);
})}
<FormItem>
<Button type="dashed" onClick={this.add}>
<Icon type="plus" />Add field
</Button>
</FormItem>
<FormItem>
<Button type="primary" htmlType="submit">
Submit
</Button>
</FormItem>
</Form>
);
}
}
export default Form.create()(TestForm);
Upvotes: 3
Views: 9294
Reputation:
You can use forceRender={true}
in the prop that holding the form to render it. I had a form inside drawer. For that i had same error. Which I used forceRender={true}
in drawer prop. So whichever holding the form, you need to render that using forceRender
.
Upvotes: 2
Reputation: 76
You should always register a field before you can use it. Here, I would suggest you to set the state with the list in componentDidMount
and then use initialValue to set the value in render. For example
componentDidMount() {
const {
form: { setFieldsValue },
listKeys,
} = this.props;
this.setState({listKeys})
}
render() {
<FormItem label="Sub1">
{getFieldDecorator(`list[${key}].sub1`, {initialValue: this.props.list[key].sub1})(
<Input placeholder="Sub1" />
)}
</FormItem>
}
Upvotes: 0