How to call onFinish method of form in child component from parent in ant design framework

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.

Answer

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>
  );
});

DEMO