Reputation: 1287
So I have a wrapper parent component that sets the layout of the application, menu and also has a save button. Child components render according to routes ( only 2-3 for now ).
I'm developing something where the position of the SAVE button is fixed ( in the parent component) and whenever the save button is pressed it should execute the save method of the child component.
I'm able to call child methods from parents using refs for now (looking for a better solution) but then I lose the onFininsh functionality provided by ANT Design Form and hence losing all validations, values of items of form, and other helpful features.
This is my Parent.
class Layout extends React.Component {
constructor(props) {
super(props);
this.child = React.createRef();
}
render() {
return(
<button onClick = {this.child.current.save }>Save</button>
<Two ref={this.child} />
)
}
}
This is my child
const ChildComponent = forwardRef((props, ref) => {
useImperativeHandle(ref, () => ({
save() {
alert("Child Function Called");
},
}));
function saveData(values) {
// How to execute this function from parent
}
return (
<Form
form={form}
{...formItemLayout}
// onFinishFailed={finishFailed}
onFinish={saveData}
>
-----
----
</Form>
)
})
I can get alerts from the save function of the child component. Also, there is a router in between both components. This may not be the best approach or maybe anti react approach but there is no harm in trying or learning anything new.
Upvotes: 0
Views: 1924
Reputation: 10429
Yes, it is still possible. Using the Form
API docs, there is a submit
method that is exposed that you can call. It will validate fields so there is no need to call validateFields
either.
There is no need to create a custom save
method since submit
will do the job. The thing is that you have to pass the ref down to the Form
component.
class Layout extends React.Component {
constructor(props) {
super(props);
this.child = React.createRef();
}
render() {
return (
<>
<button onClick={() => this.child.current.submit()}>Save</button>
<DemoForm ref={this.child} />
</>
);
}
}
const DemoForm = forwardRef((props, ref) => {
const onFinish = (values) => {
console.log('Success:', values);
};
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
return (
<Form
ref={ref}
name="basic"
labelCol={{
span: 8,
}}
wrapperCol={{
span: 16,
}}
initialValues={{
remember: true,
}}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
<Form.Item
label="Username"
name="username"
rules={[
{
required: true,
message: 'Please input your username!',
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="Password"
name="password"
rules={[
{
required: true,
message: 'Please input your password!',
},
]}
>
<Input.Password />
</Form.Item>
<Form.Item
name="remember"
valuePropName="checked"
wrapperCol={{
offset: 8,
span: 16,
}}
>
<Checkbox>Remember me</Checkbox>
</Form.Item>
<Form.Item
wrapperCol={{
offset: 8,
span: 16,
}}
>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
);
});
Upvotes: 2