javascript — React, Formik и реализация Repeatable Fields Fields (как формы с несколькими полями)

Реагирование, Formik и реализация Repeatable Fields Fields (как формы с несколькими полями)

Я пытаюсь выяснить, как использовать реагировать с formik для интеграции повторяющихся полей формы в моей форме. В документации formik приведено описание работы полевых массивов . Я прочитал это миллион раз и не достаточно умен, чтобы понять это.

Я также прочитал этот пост, который включает в себя пример и которому я пытался следовать, изучая, как сделать повторяемый элемент формы.

Ранее я задавал этот вопрос и пытался работать с советами, но столкнулся с ошибками, показанными в этом стеке . Я не могу понять, как их решить.

Кто-то из раздоров предоставил этот пример песочницы кода, чтобы показать, как должны работать воспроизводимые поля. Я изо всех сил пытаюсь приспособить этот пример, чтобы использовать мою форму в ее контексте. Я не могу заставить работать элемент remove вообще, пока не попробую встроить отдельный компонент с несколькими полями формы вместо одного элемента формы с названием title.

Я пытаюсь:

  1. У родительской формы есть кнопка с надписью добавить запрос данных;

  2. Когда эта кнопка нажата, отобразите другую форму (с несколькими вопросами, в настоящее время настроенную как отдельный компонент класса), которая задает вопросы для этих запросов данных.

  3. Есть кнопка с надписью «удалить этот запрос данных», чтобы можно было удалить заполненный элемент формы

  4. Повторите шаги 1-3, описанные выше, чтобы можно было выполнить несколько запросов данных.

Самое близкое к этому начало работы — песочница в коде выше, но я пытаюсь заменить один элемент формы заголовка компонентом формы DataRequests.jsx, в котором есть несколько полей формы.

Кто-нибудь может увидеть, как это сделать?

Чтобы изложить код в этом посте, моя основная форма имеет:

 import React from "react"; import ReactDOM from "react-dom"; import DataRequests from "./DataRequests"; // import { fsDB, firebase, settings } from "../../../firebase"; import { Formik, Form, Field, FieldArray, ErrorMessage, withFormik } from "formik"; // import * as Yup from "yup"; import Select from "react-select"; import { Badge, Button, Col, ComponentClass, Feedback, FormControl, FormGroup, FormLabel, InputGroup, Table, Row, Container } from "react-bootstrap"; const style2 = { paddingTop: "2em" } const initialValues = { title: "", DataRequests: [], FundingRequests: [], createdAt: '' } class ProjectForm extends React.Component { state = { options: [], } async componentDidMount() { // const fsDB = firebase.firestore(); // Don't worry about this line if it comes from your config. let options = []; // await fsDB.collection("abs_for_codes").get().then(function (querySnapshot) { // querySnapshot.forEach(function(doc) { // console.log(doc.id, ' ={amp}gt; ', doc.data()); // options.push({ // value: doc.data().title.replace(/( )/g, ''), // label: doc.data().title   ' - ABS '   doc.id // }); // }); // }); this.setState({ options }); } handleSubmit = (formState, { resetForm }) ={amp}gt; { // Now, you're getting form state here! const payload = { ...formState, // resourceOffers: formState.resourceOffers.map(t ={amp}gt; t.value), // ethicsIssue: formState.ethicsIssue.map(t ={amp}gt; t.value), // disclosureStatus: formState.disclosureStatus.value, createdAt: firebase.firestore.FieldValue.serverTimestamp() } console.log("formvalues", payload); fsDB .collection("project") .add(payload) .then(docRef ={amp}gt; { console.log("docRef{amp}gt;{amp}gt;{amp}gt;", docRef); resetForm(initialValues); }) .catch(error ={amp}gt; { console.error("Error adding document: ", error); }); }; render() { const { options } = this.state; return( {amp}lt;Formik initialValues={initialValues} // validationSchema={Yup.object().shape({ // title: Yup.string().required("Give your proposal a title") // })} onSubmit={this.handleSubmit} render={({ errors, status, touched, setFieldValue, setFieldTouched, handleSubmit, isSubmitting, dirty, values, arrayHelpers }) ={amp}gt; { return ( {amp}lt;div{amp}gt; {amp}lt;div className="formbox"{amp}gt; {amp}lt;Form{amp}gt; {amp}lt;Table responsive{amp}gt; {amp}lt;thead{amp}gt; {amp}lt;tr{amp}gt; {amp}lt;th{amp}gt;#{amp}lt;/th{amp}gt; {amp}lt;th{amp}gt;Element{amp}lt;/th{amp}gt; {amp}lt;th{amp}gt;Insights{amp}lt;/th{amp}gt; {amp}lt;/tr{amp}gt; {amp}lt;/thead{amp}gt; {amp}lt;/Table{amp}gt; {/*General*/} {amp}lt;h5 className="formheading"{amp}gt;general{amp}lt;/h5{amp}gt; {amp}lt;Table responsive{amp}gt; {amp}lt;tbody{amp}gt; {amp}lt;tr{amp}gt; {amp}lt;td{amp}gt;1{amp}lt;/td{amp}gt; {amp}lt;td{amp}gt; {amp}lt;div className="form-group"{amp}gt; {amp}lt;label htmlFor="title"{amp}gt;Title{amp}lt;/label{amp}gt; {amp}lt;Field name="title" type="text" className={ "form-control"   (errors.title {amp}amp;{amp}amp; touched.title ? " is-invalid" : "") } /{amp}gt; {amp}lt;ErrorMessage name="title" component="div" className="invalid-feedback" /{amp}gt; {amp}lt;/div{amp}gt; {amp}lt;/td{amp}gt; {amp}lt;td className="forminsight"{amp}gt;No insights{amp}lt;/td{amp}gt; {amp}lt;/tr{amp}gt; {amp}lt;/tbody{amp}gt; {amp}lt;/Table{amp}gt; {/*Resources s*/} {amp}lt;h5 className="formheading"{amp}gt;resources{amp}lt;/h5{amp}gt; {amp}lt;Table responsive{amp}gt; {amp}lt;tbody{amp}gt; {amp}lt;/tbody{amp}gt; {amp}lt;/Table{amp}gt; {amp}lt;h6 className="formheading"{amp}gt;Repeatable data form{amp}lt;/h6{amp}gt; {amp}lt;Table responsive{amp}gt; {amp}lt;tbody{amp}gt; {amp}lt;tr{amp}gt; {amp}lt;td{amp}gt;2 {amp}lt;/td{amp}gt; {amp}lt;td{amp}gt; {amp}lt;label htmlFor="DataRequests"{amp}gt;Add a Data Request{amp}lt;/label{amp}gt; {amp}lt;Table responsive{amp}gt; {amp}lt;tbody{amp}gt; {amp}lt;tr{amp}gt; {amp}lt;td{amp}gt;12 {amp}lt;/td{amp}gt; {amp}lt;td{amp}gt;{amp}lt;label htmlFor="DataRequests"{amp}gt;Add a Funding Request{amp}lt;/label{amp}gt; {/* {amp}lt;FieldArray name="fundingRequests" component={FundingRequests} /{amp}gt; */} {amp}lt;tr{amp}gt; {amp}lt;td{amp}gt; {amp}lt;div{amp}gt; {amp}lt;FieldArray name="dataRequests" component={DataRequests} render={arrayHelpers ={amp}gt; ( {amp}lt;React.Fragment{amp}gt; {values.repeatable.map((r, i) ={amp}gt; ( {amp}lt;div{amp}gt; {amp}lt;label for={`repeatable.${i}.title`}{amp}gt;Title for {i}{amp}lt;/label{amp}gt; {amp}lt;Field name={`repeatable.${i}.title`} /{amp}gt; {amp}lt;Button variant="outline-primary" size="sm" onClick={() ={amp}gt; arrayHelpers.remove({ title: "" })} {amp}gt; Remove this Request {amp}lt;/Button{amp}gt; {amp}lt;/div{amp}gt; ))} {amp}lt;div{amp}gt; {amp}lt;button type="button" onClick={() ={amp}gt; arrayHelpers.push({ title: "" })} {amp}gt; Add repeatable thing {amp}lt;/button{amp}gt; {amp}lt;/div{amp}gt; {amp}lt;/React.Fragment{amp}gt; )} /{amp}gt; {amp}lt;/div{amp}gt; {amp}lt;/td{amp}gt; {amp}lt;/tr{amp}gt; {amp}lt;/td{amp}gt; {amp}lt;td className="forminsight"{amp}gt;No insights{amp}lt;/td{amp}gt; {amp}lt;/tr{amp}gt; {amp}lt;/tbody{amp}gt; {amp}lt;/Table{amp}gt; {amp}lt;div className="form-group"{amp}gt; {amp}lt;Button variant="outline-primary" type="submit" id="ProjectId" onClick={handleSubmit} disabled={!dirty || isSubmitting} {amp}gt; Save {amp}lt;/Button{amp}gt; {amp}lt;/div{amp}gt; {amp}lt;/Form{amp}gt; {amp}lt;/div{amp}gt; {amp}lt;/div{amp}gt; ); }} /{amp}gt; ); } } export default ProjectForm; ReactDOM.render({amp}lt;ProjectForm /{amp}gt;, document.getElementById("root")); 

В приведенном выше коде я оставляю один элемент формы (для заголовка) из примера изолированной программной среды кода, чтобы показать суть того, что я хочу сделать — эту позицию следует заменить компонентами формы в форме запроса, которые перечислены ниже. :

 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: "", disclosure: "" }; 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" } ]; class DataRequests extends React.Component { render() { // Get the parent form props. This is where you should set the form values. const {form: parentForm, ...parentProps} = this.props; return ( {amp}lt;Formik initialValues={initialValues} render={({ values, form, push, remove, index, setFieldTouched }) ={amp}gt; { return ( {amp}lt;div{amp}gt; {/* if i uncomment this line, i get loads of type errors saying that values is not defined {parentForm.values.dataRequests.map((_notneeded, index) ={amp}gt; { return ( */} {amp}lt;div key={index}{amp}gt; {amp}lt;Table responsive{amp}gt; {amp}lt;tbody{amp}gt; {amp}lt;tr{amp}gt; {amp}lt;td{amp}gt; {amp}lt;div className="form-group"{amp}gt; {amp}lt;label htmlFor="dataRequestsTitle"{amp}gt;Title{amp}lt;/label{amp}gt; {amp}lt;Field name={`dataRequests.${index}.title`} placeholder="Add a title" className="form-control" onChange={e ={amp}gt; { parentForm.setFieldValue( `dataRequests.${index}.title`, e.target.value ); }} {amp}gt;{amp}lt;/Field{amp}gt; {amp}lt;/div{amp}gt; {amp}lt;/td{amp}gt; {amp}lt;/tr{amp}gt; {amp}lt;tr{amp}gt; {amp}lt;td{amp}gt; {amp}lt;div className="form-group"{amp}gt; {amp}lt;label htmlFor="dataRequestsDescription"{amp}gt; Description {amp}lt;/label{amp}gt; {amp}lt;Field name={`dataRequests.${index}.description`} component="textarea" rows="10" placeholder="Describe the data you're looking to use" className="form-control" onChange={e ={amp}gt; { parentForm.setFieldValue( `dataRequests.${index}.description`, e.target.value ); }} {amp}gt;{amp}lt;/Field{amp}gt; {amp}lt;/div{amp}gt; {amp}lt;/td{amp}gt; {amp}lt;/tr{amp}gt; {amp}lt;tr{amp}gt; {amp}lt;td{amp}gt; {amp}lt;div className="form-group"{amp}gt; {amp}lt;label htmlFor="dataType"{amp}gt; Are you looking for primary (raw) data or secondary data? {amp}lt;/label{amp}gt; {amp}lt;Select key={`my_unique_select_keydataType`} name={`dataRequests.${index}.dataType`} className={"react-select-container"} classNamePrefix="react-select" value={values.dataTypes} onChange={({ value: selectedOption }) ={amp}gt; { console.log(selectedOption); // Setting field value - name of the field and values chosen. parentForm.setFieldValue( `dataRequests.${index}.dataType`, selectedOption ); }} onBlur={setFieldTouched} options={dataTypes} /{amp}gt; {amp}lt;/div{amp}gt; {amp}lt;/td{amp}gt; {amp}lt;/tr{amp}gt; {amp}lt;tr{amp}gt; {amp}lt;td{amp}gt; {amp}lt;div className="form-group"{amp}gt; {amp}lt;label htmlFor="dataRequestsSource"{amp}gt; Do you know who or what sort of entity may have this data? {amp}lt;/label{amp}gt; {amp}lt;Field name={`dataRequests.${index}.source`} component="textarea" rows="10" placeholder="Leave blank and skip ahead if you don't" className="form-control" onChange={e ={amp}gt; { parentForm.setFieldValue( `dataRequests.${index}.source`, e.target.value ); }} {amp}gt;{amp}lt;/Field{amp}gt; {amp}lt;/div{amp}gt; {amp}lt;/td{amp}gt; {amp}lt;/tr{amp}gt; {amp}lt;tr{amp}gt; {amp}lt;td{amp}gt; {amp}lt;div className="form-group"{amp}gt; {amp}lt;label htmlFor="dataRequestsDisclosure"{amp}gt; Do you anticipate disclosing this data? {amp}lt;/label{amp}gt; {amp}lt;Field name={`dataRequests.${index}.disclosure`} component="textarea" rows="10" placeholder="Describe uses which may involve disclosure" className="form-control" onChange={e ={amp}gt; { parentForm.setFieldValue( `dataRequests.${index}.disclosure`, e.target.value ); }} {amp}gt;{amp}lt;/Field{amp}gt; {amp}lt;/div{amp}gt; {amp}lt;/td{amp}gt; {amp}lt;/tr{amp}gt; {amp}lt;tr{amp}gt; {amp}lt;Button variant="link" size="sm" onClick={() ={amp}gt; parentProps.remove(index)} {amp}gt; Remove this Data Request {amp}lt;/Button{amp}gt; {amp}lt;/tr{amp}gt; {amp}lt;/tbody{amp}gt; {amp}lt;/Table{amp}gt; {amp}lt;/div{amp}gt; {/* );}) } */} {amp}lt;Button variant="outline-primary" size="sm" onClick={() ={amp}gt; parentProps.push(initialValues)} {amp}gt; Add Data Request {amp}lt;/Button{amp}gt; {amp}lt;/div{amp}gt; ); }} /{amp}gt; ); } } export default DataRequests; 

Итак, как вы можете видеть, все это большой беспорядок. Это продукт попытки решить этот КАЖДЫЙ день с мая этого года. Я явно не умный, но у меня закончились идеи о том, где искать дальше, чтобы попытаться учиться.

Я попытался изменить код Formik, чтобы использовать несколько полей формы внутри повторяемого FieldArray следующим образом. При этом я удалил оператор «repeatable» из функции map, но это вызывает ошибку, которую я не знаю, как отлаживать.

 const initialValues = { title: "", type: "", identifier: "", proposedUse: "", relatedRights: "" }; {amp}lt;Formik initialValues={initialValues} render={({ values }) ={amp}gt; ( {amp}lt;Form{amp}gt; {amp}lt;FieldArray render={arrayHelpers ={amp}gt; ( {amp}lt;React.Fragment{amp}gt; {values.map((r, i) ={amp}gt; ( {amp}lt;div{amp}gt; {amp}lt;label for={`repeatable.${i}.title`}{amp}gt;Title{amp}lt;/label{amp}gt; {amp}lt;Field name={`repeatable.${i}.title`} /{amp}gt; {amp}lt;label for={`repeatable.${i}.classification`}{amp}gt;Classification{amp}lt;/label{amp}gt; {amp}lt;Field name={`repeatable.${i}.classification`} /{amp}gt; {amp}lt;label for={`repeatable.${i}.identifier`}{amp}gt;Identifier{amp}lt;/label{amp}gt; {amp}lt;Field name={`repeatable.${i}.identifier`} /{amp}gt; {amp}lt;label for={`repeatable.${i}.proposedUse`}{amp}gt;Proposed Use{amp}lt;/label{amp}gt; {amp}lt;Field name={`repeatable.${i}.proposedUse`} /{amp}gt; {amp}lt;label for={`repeatable.${i}.relatedRights`}{amp}gt;Related Rights{amp}lt;/label{amp}gt; {amp}lt;Field name={`repeatable.${i}.relatedRights`} /{amp}gt; {amp}lt;div{amp}gt; {amp}lt;button type="button" onClick={() ={amp}gt; arrayHelpers.remove({ values })} {amp}gt; Remove repeatable thing {amp}lt;/button{amp}gt; {amp}lt;/div{amp}gt; {amp}lt;/div{amp}gt; ))} {amp}lt;div{amp}gt; {amp}lt;button type="button" onClick={() ={amp}gt; arrayHelpers.push({ values })} {amp}gt; Add repeatable thing {amp}lt;/button{amp}gt; {amp}lt;/div{amp}gt; {amp}lt;/React.Fragment{amp}gt; )} /{amp}gt; {amp}lt;/Form{amp}gt; )} /{amp}gt; 

Любые советы о том, как решить эту проблему, будут с благодарностью приняты.

Понравилась статья? Поделиться с друзьями:
JavaScript & TypeScript
Adblock
detector