React—Modal 的确认按钮在 Form 之外,且用到onRef父调子

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React—Modal 的确认按钮在 Form 之外,且用到onRef父调子相关的知识,希望对你有一定的参考价值。

参考技术A react 中, Modal 中嵌套 Form子组件 ,提交按钮在 Modal的footer 中(也可用函数组件,本例用 class Component 写的, antd4.x ,初次使用 react 记录一下)

将 Ant Design Form 与 Modal 集成

【中文标题】将 Ant Design Form 与 Modal 集成【英文标题】:Integrate Ant Design Form with Modal 【发布时间】:2021-06-06 00:32:01 【问题描述】:

我是 React 和 JS 的新手,我目前正在尝试创建一个组件来将 antd 表单与 modal 集成,以便我可以利用表单功能,例如“验证”。

这是我的代码:

发布请求的函数:

import baseUrl from "./baseUrl";

export async function _postSchoolRollOutRequest(schoolRollOutRequestForm) 
  try 
    const response = await fetch(
      `$baseUrl/feedbacks/request/schoolRollOutRequest`,
      
        method: "POST",
        headers: 
          Accept: "application/json",
          "Content-Type": "application/json",
        ,
        body: JSON.stringify(schoolRollOutRequestForm),
      
    );
    const data = await response.json();
    console.log("Post school roll out form success!");
    return data;
   catch (e) 
    console.log("Post school roll out form failed!", e);
  

表单与模态集成的组件:

import React,  useState  from "react";
import  Modal, Button, Form, Input, Radio  from "antd";
import  _postSchoolRollOutRequest  from "../../api/feedbacksApi";

import "./PopUp.scss";

export default (props) => 
  const FormItem = Form.Item;

  const [visible, setVisible] = useState(false);
  const showModal = () => 
    setVisible(true);
  ;

  const handleOk = (schoolRollOutRequestForm) => 
    _postSchoolRollOutRequest(schoolRollOutRequestForm);
    setVisible(false);
  ;

  const handleCancel = () => 
    setVisible(false);
  ;

  return (
    <>
      <Button type="primary" onClick=showModal>
        Roll-out My School!
      </Button>
      <Modal
        destroyOnClose=true
        visible=visible
        title="Roll-out Request"
        onCancel=handleCancel
        footer=[
          <Button
            block
            key="submit"
            type="primary"
            onClick=(feedbackSubmission) =>
              handleOk(
                shoolName: feedbackSubmission.shoolName,
                otherFeedback: feedbackSubmission.otherFeedback,
                contact: feedbackSubmission.contact,
              )
            
          >
            Roll-out My School!
          </Button>,
        ] 
        width=400
      >
        <div className="modal-body center">
          <Form layout="vertical">
            <Form.Item
              label="Schools Name"
              name="schoolName"
              rules=[ required: true ]
            >
              <Input type="text" label="schoolName" placeholder="UT Austin" />
            </Form.Item>
            <FormItem
              label="Any other requirements/feedback (optional)"
              name="otherFeedback"
            >
              <Input type="textarea" placeholder="abcd..." />
            </FormItem>
            <FormItem label="How do we contact you? (optional)" name="contact">
              <Input type="text" placeholder="abcd@email.com" />
            </FormItem>
          </Form>
        </div>
      </Modal>
    </>
  );
;

然而,我遇到了两个让我很困惑的问题:

    我认为页脚处的按钮不会触发表单的 onFinish,因此表单的验证不起作用,我想知道我是否能获得任何关于我的情况的最佳实践的线索?

    我尝试为“handleOk”伪造一个 json,然后为“_postSchoolRollOutRequest”伪造一个 json,但我的后端似乎收到了一个带有空负载的请求,我是否也能获得有关此问题的任何见解?

【问题讨论】:

【参考方案1】:

代码沙盒: https://codesandbox.io/s/antdesignmodalform-***-3yv4h?file=/index.js:920-3529

首先提交按钮应该在表单标签内。如果它在表单标签之外,则需要使用表单属性来触发它。

在您的情况下,模式总是在表单之外,因此您必须将提交按钮与表单链接。

这是使用 ANT 设计实现它的方法。

Action Handler 代码(如果您使用的是 redux,则根据您的要求修改回调部分)

export async function _postSchoolRollOutRequest(
  schoolRollOutRequestForm,
  callback
) 
  const baseUrl = "http://testing.com";

  console.log("form values", schoolRollOutRequestForm);
  try 
    const response = await fetch(
      `$baseUrl/feedbacks/request/schoolRollOutRequest`,
      
        method: "POST",
        headers: 
          Accept: "application/json",
          "Content-Type": "application/json"
        ,
        body: JSON.stringify(schoolRollOutRequestForm)
      
    );
    const data = await response.json();
    console.log("Post school roll out form success!");

    callback(response.status, data);
   catch (e) 
    callback(e.status);
    console.log("Post school roll out form failed!", e);
  

表单组件

const FormModal = () => 
  const [form] = Form.useForm();
  const [visible, setVisible] = useState(false);
  const [postData, setPostData] = useState(
    loading: false,
    error: false,
    data: []
  );

  const onSubmit = (values) => 
    setPostData( ...postData, loading: true, error: false );
    _postSchoolRollOutRequest(values, (status, data) => 
      if (status === 200) 
        form.resetFields();
        setPostData( ...postData, loading: false, data: data );
       else 
        setPostData(
          ...postData,
          loading: false,
          error: true,
          data: "Post school roll out form failed!"
        );
      
    );
  ;

  return (
    <>
      <Button
        type="primary"
        onClick=() => 
          setVisible(true);
        
      >
        click to open form
      </Button>
      <Modal
        visible=visible
        title="Post  data"
        okText="Submit"
        cancelText="Cancel"
        onCancel=() => 
          setVisible(false);
        
        footer=[
          <Button key="cancel" onClick=() => setVisible(false)>
            Cancel
          </Button>,
          <Button
            key="submit"
            type="primary"
            loading=postData.loading
            onClick=() => 
              form
                .validateFields()
                .then((values) => 
                  onSubmit(values);
                )
                .catch((info) => 
                  console.log("Validate Failed:", info);
                );
            
          >
            Submit
          </Button>
        ]
      >
        <Form
          form=form
          layout="vertical"
          name="form_in_modal"
          initialValues=
            modifier: "public"
          
        >
          <Form.Item
            label="Schools Name"
            name="schoolName"
            rules=[
              
                required: true,
                message: ""
              
            ]
          >
            <Input />
          </Form.Item>
          <Form.Item
            label="Any other requirements/feedback (optional)"
            name="otherFeedback"
          >
            <Input type="textarea" />
          </Form.Item>
          <Form.Item label="How do we contact you? (optional)" name="contact">
            <Input />
          </Form.Item>

          postData.error && (
            <>
              <br />
              <span style= color: "red" >postData.data</span>
            </>
          )
        </Form>
      </Modal>
    </>
  );
;

【讨论】:

以上是关于React—Modal 的确认按钮在 Form 之外,且用到onRef父调子的主要内容,如果未能解决你的问题,请参考以下文章

RN-第三方之react-native-root-modal、或者modal实现侧栏效果

Modal和Form结合的 表单对话框 _react

微信小程序之----弹框组件modal

在按钮上打开 react-native Modal 单击操作表选项

将 Ant Design Form 与 Modal 集成

react-native-modal 内的导航