首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >React Formik字段数组-实现可重复的表单字段

React Formik字段数组-实现可重复的表单字段
EN

Stack Overflow用户
提问于 2019-10-13 01:22:46
回答 2查看 4K关注 0票数 3

我试图遵循使用FieldArrays的Formik文档,以便向表单中添加可重复的表单元素。

我还看到这个中型员额给出了一个例子。

我学习缓慢,无法将文档和实现之间的点连接起来。

我想在我的主表单中有一个按钮,上面写着:“添加数据请求”。

如果选择了该按钮,则会显示一个嵌套表单,列出数据配置文件,以及“添加另一个数据请求”和“删除”按钮。

我已经在我的应用程序中的另一个组件中创建了嵌套表单,但是我很难找到如何使用中介post中的示例来合并嵌套表单(作为一个可重复的元素--即有人可能想要5个数据请求)。

有什么例子说明如何实现这一点吗?

在我的代码中,我基本上遵循了中间的post,但是尝试将数据请求表单组件链接到索引中。

代码语言:javascript
运行
复制
<button 
      type="button"
      onClick={() => arrayHelpers.insert(index, <DataRequestForm />)}>
      Add a data request
</button>   

这显然是不正确的,但我无法掌握如何做到这一点。

接受Nithin的回答,我尝试修改嵌入的表单,以便我可以使用react select,如下所示,但是我得到了一个错误,上面写着:

TypeError:无法读取未定义的属性值

代码语言:javascript
运行
复制
import React from "react";
import { Formik, Form, Field, FieldArray, ErrorMessage, withFormik } from "formik";
import Select from "react-select";


import {
  Button,
  Col,
  FormControl,
  FormGroup,
  FormLabel,
  InputGroup,
  Table,
  Row,
  Container
} from "react-bootstrap";

const initialValues = {
  dataType: "",
  title: "",
  description: '',
  source: '',

}


class DataRequests extends React.Component {

  render() {
    const dataTypes = [
      { value: "primary", label: "Primary (raw) data sought" },
      { value: "secondary", label: "Secondary data sought"},
      { value: "either", label: "Either primary or secondary data sought"},
      { value: "both", label: "Both primary and secondary data sought"}
    ]

    return(
      <Formik
          initialValues={initialValues}
          render={({ 
            form, 
            remove, 
            push,
            errors, 
            status, 
            touched, 
            setFieldValue,
            setFieldTouched, 
            handleSubmit, 
            isSubmitting, 
            dirty, 
            values 
          }) => {
          return (
            <div>
                {form.values.dataRequests.map((_notneeded, index) => {
                return (
                  <div key={index}>
                    <Table responsive>
                      <tbody>
                        <tr>
                          <td>
                            <div className="form-group">
                              <label htmlFor="dataRequestsTitle">Title</label>
                              <Field
                                name={`dataRequests.${index}.title`}
                                placeholder="Add a title"
                                className={"form-control"}
                              >
                              </Field>
                            </div>
                          </td>
                        </tr>
                        <tr>
                            <td>
                              <div className="form-group">
                                <label htmlFor="dataRequestsDescription">Description</label>
                                  <Field
                                    name={`dataRequests.${index}.description`}
                                    component="textarea"
                                    rows="10"
                                    placeholder="Describe the data you're looking to use"
                                    className={
                                      "form-control"}
                                  >
                                  </Field>
                              </div>    
                            </td>
                        </tr>
                        <tr>
                          <td>
                            <div className="form-group">
                              <label htmlFor="dataRequestsSource">Do you know who or what sort of entity may have this data?</label>
                                <Field
                                  name={`dataRequests.${index}.source`}
                                  component="textarea"
                                  rows="10"
                                  placeholder="Leave blank and skip ahead if you don't"
                                  className={
                                    "form-control"}
                                >
                                </Field>
                            </div>    
                          </td>
                        </tr>
                        <tr>
                          <td>
                            <div className="form-group">
                              <label htmlFor="dataType">
                              Are you looking for primary (raw) data or secondary data?
                              </label>

                              <Select
                              key={`my_unique_select_keydataType`}
                              name={`dataRequests.${index}.source`}
                              className={
                                  "react-select-container"
                              }
                              classNamePrefix="react-select"
                              value={values.dataTypes}
                              onChange={selectedOptions => {
                                  // Setting field value - name of the field and values chosen.
                                  setFieldValue("dataType", selectedOptions)}
                                  }
                              onBlur={setFieldTouched}
                              options={dataTypes}
                              />

                            </div>    
                          </td>
                        </tr>

                        <tr>
                          <Button variant='outline-primary' size="sm" onClick={() => remove(index)}>
                            Remove
                          </Button>
                        </tr>
                      </tbody>
                    </Table>    
                  </div>
                );
              })}
              <Button
                variant='primary' size="sm"
                onClick={() => push({ requestField1: "", requestField2: "" })}
              >
                Add Data Request
              </Button>

            </div>
          )
          }
          }
      />
    );  
  };
};


export default DataRequests;
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-10-13 09:11:51

不能在窗体元素中添加嵌套窗体。请参阅下面的帖子,以了解模式细节。

你能嵌套html表单吗?

如果您希望在主窗体内嵌套具有嵌套结构的多个字段,则可以使用FieldArrays实现它。

您可以像这样构造表单。

代码语言:javascript
运行
复制
{
    firstName: "",
    lastName: "",
    dataRequests: []
  }

在这里,firstNamelastName是顶级表单字段,dataRequests可以是一个数组,其中每个元素都遵循结构

代码语言:javascript
运行
复制
{
  requestField1: "",
  requestField2: ""
}

由于dataRequests是一个数组,为了呈现FieldArray的每一项,您需要一个映射函数。

代码语言:javascript
运行
复制
form.values.dataRequests.map( render function() )

对于每个呈现的项,更改处理程序应该针对它们的索引来更新FieldArray中的正确项。

代码语言:javascript
运行
复制
 <div key={index}>
            <Field
              name={`dataRequests.${index}.requestField1`}
              placeholder="requestField1"
            ></Field>
            <Field
              name={`dataRequests.${index}.requestField2`}
              placeholder="requestField2"
            ></Field>
            <button type="button" onClick={() => remove(index)}>
              Remove
            </button>
          </div>

在上面的片段中,name={dataRequests.${index}.requestField1}要求formik用输入字段的值更新dataRequests数组的nth元素的键requestField1

最后,您的<DataRequest />组件可能如下所示。

代码语言:javascript
运行
复制
import React from "react";
import { Field } from "formik";

export default ({ form, remove, push }) => {
  return (
    <div>
      {form.values.dataRequests.map((_notneeded, index) => {
        return (
          <div key={index}>
            <Field
              name={`dataRequests.${index}.requestField1`}
              placeholder="requestField1"
            ></Field>
            <Field
              name={`dataRequests.${index}.requestField2`}
              placeholder="requestField2"
            ></Field>
            <button type="button" onClick={() => remove(index)}>
              Remove
            </button>
          </div>
        );
      })}
      <button
        type="button"
        onClick={() => push({ requestField1: "", requestField2: "" })}
      >
        Add Data Request
      </button>
    </div>
  );
};

使用<FieldArray />,您可以将<DataRequest />连接到主窗体。

您可以尝试下面的示例,以便代码片段

代码语言:javascript
运行
复制
function DataRequests({ form, remove, push }){
  return (
    <div>
      {form.values.dataRequests.map((_notneeded, index) => {
        return (
          <div key={index}>
            <Formik.Field
              name={`dataRequests.${index}.requestField1`}
              placeholder="requestField1"
            ></Formik.Field>
            <Formik.Field
              name={`dataRequests.${index}.requestField2`}
              placeholder="requestField2"
            ></Formik.Field>
            <button type="button" onClick={() => remove(index)}>
              Remove
            </button>
          </div>
        );
      })}
      <button
        type="button"
        onClick={() => push({ requestField1: "", requestField2: "" })}
      >
        Add Data Request
      </button>
    </div>
  );
};


class Home extends React.Component {
  initialValues = {
    firstName: "",
    lastName: "",
    dataRequests: []
  };
  state = {};
  render() {
    return (
      <div>
        <Formik.Formik
          initialValues={this.initialValues}
          onSubmit={values => {
            this.setState({ formData: values });
          }}
        >
          {() => {
            return (
              <Formik.Form>
                <div>
                  <Formik.Field
                    name="firstName"
                    placeholder="First Name"
                  ></Formik.Field>
                </div>
                <div>
                  <Formik.Field
                    name="lastName"
                    placeholder="Last Name"
                  ></Formik.Field>
                </div>
                <Formik.FieldArray name="dataRequests" component={DataRequests} />
                <button type="submit">Submit</button>
              </Formik.Form>
            );
          }}
        </Formik.Formik>
        {this.state.formData ? (
          <code>{JSON.stringify(this.state.formData, null, 4)}</code>
        ) : null}
      </div>
    );
  }
}

ReactDOM.render(<Home />, document.getElementById("root"))
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/formik/dist/formik.umd.production.js"></script>

<div id="root"></div>

票数 7
EN

Stack Overflow用户

发布于 2019-10-21 22:29:17

对于任何想从这篇文章中学习的人来说,nithin对这个问题的回答显然是出于好意,但这并不是formik的正确部署。您可以在这里查看一个代码沙箱:https://codesandbox.io/embed/goofy-glade-lx65p?fontsize=14用于当前解决此问题的尝试(仍未修复),但向解决方案迈出了更好的一步。同样感谢你对这个问题的回答背后的有益意图。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58359867

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档