简体   繁体   中英

Validating Final Form Array on Click

I am building an application with React Final Form. In the form, user needs to fill up basic input fields as well as add questions with its choices. For the questions and choices I am using FieldArray feature. So, until here everything is good and working. However, I would like to add another functionality to this form.

As you can see in the image below, this is a Card component rendered inside FieldArray . Every time user clicks Add a Question button, There will be another Card component on the page.

The feature I need is to make the Save button work on top-right corner. At the moment I don't know how should I implement the Save button but what I wanna achieve is that I want to toggle the Card component in the image to another Card component, where I display the input data by using fields.value . So, no input field. However, I want to also validate this portion of the form when I click save. This is what I don't know how to do. So, every Save button will validate its own fields and if validation passes, the Card will be toggled to another Card component where the data is read-only.

So, I need your suggestion for the validation part as well as your opinion to add this functionality.

Thanks

在此处输入图片说明

Edit

I've been reading the docs of FinalForm as well as ReduxForm to figure out how can I handle this situation but I couldn't figure it out yet.

I've checked the Wizard example in FinalForm docs. However I am not sure if it's suitable for my situation. Wizard has a single <form> tag present at all times on a page and when a user clicks next button, input fields switch. In my case, I might need multiple form tags as you mentioned.

I've put 3 form structures as an example. Can you tell me which way is to go?

import { Form as FinalForm } from 'react-final-form'

#1 Basic Form:

Classic way of structuring the form and it is the current situation. So, this is not the way to solve the issue.

      <FinalForm onSubmit={aCustomSubmitFunction}>
        {
          ({ handleSubmit }) => {
            return (
              <form onSubmit={handleSubmit}>
                <Field name='firstName'>{({input}) => <input {...input} />}</Field>
                <Field name='lastName'>{({input}) => <input {...input} />}</Field>
                <FieldArray name='questions'>
                  {({ fields }) => (
                    <div>
                      {fields.map((name, index) => {
                        return (
                          <div className="card">
                            <Field name={`${name}.question`}>{({input}) => <input {...input} type="text" />}</Field>
                            <button type="button" onClick={() => fields.remove(index)}>Delete</button>
                            <button type="submit">Save</button>
                          </div>
                        )
                      })}
                      <button type="button" onClick={() => fields.push({ question: undefined })}>Add a Question</button>
                    </div>
                  )}
                </FieldArray>
                <button type="submit">Submit</button>
              </form>
            )
          }
        }
      </FinalForm>

#2 Multiple forms under a single FinalForm:

Multiple forms inside a FinalForm. This seems to be the way to go, however 'save' button submits the entire form not its own form. It is using the same handleSubmit so this must be the reason, though how can I have a different handleSubmit? Wrapping the form tag that is inside FieldArray with another FinalForm ?

      <FinalForm onSubmit={aCustomSubmitFunction}>
        {
          ({ handleSubmit }) => {
            return (
              <>
                <form onSubmit={handleSubmit}>
                  <Field name='firstName'>{({input}) => <input {...input} />}</Field>
                  <Field name='lastName'>{({input}) => <input {...input} />}</Field>
                  <button type="submit">Submit</button>
                </form>
                <FieldArray name='questions'>
                  {({ fields }) => (
                    <div>
                      {fields.map((name, index) => {
                        return (
                          <form onSubmit={handleSubmit}>
                            <div className="card">
                              <Field name={`${name}.question`}>{({input}) => <input {...input} type="text" />}</Field>
                              <button type="button" onClick={() => fields.remove(index)}>Delete</button>
                              <button type="submit">Save</button>
                            </div>
                          </form>
                        )
                      })}
                      <button type="button" onClick={() => fields.push({ question: undefined })}>Add a Question</button>
                    </div>
                  )}
                </FieldArray>
              </>
            )
          }
        }
      </FinalForm>

#3 Multiple nested forms under a single FinalForm:

This is invalid html. So this must be wrong approach but while I was doing a research I found a thing called React Portals, which might be helpful but I think it's unnecessary.

      <FinalForm onSubmit={aCustomSubmitFunction}>
        {
          ({ handleSubmit }) => {
            return (
              <form onSubmit={handleSubmit}>
                <Field name='firstName'>{({input}) => <input {...input} />}</Field>
                <Field name='lastName'>{({input}) => <input {...input} />}</Field>
                <FieldArray name='questions'>
                  {({ fields }) => (
                    <div>
                      {fields.map((name, index) => {
                        return (
                          <form>
                            <div className="card">
                              <Field name={`${name}.question`}>{({input}) => <input {...input} type="text" />}</Field>
                              <button type="button" onClick={() => fields.remove(index)}>Delete</button>
                              <button type="submit">Save</button>
                            </div>
                          </form>
                        )
                      })}
                      <button type="button" onClick={() => fields.push({ question: undefined })}>Add a Question</button>
                    </div>
                  )}
                </FieldArray>
                <button type="submit">Submit</button>
              </form>
            )
          }
        }
      </FinalForm>

To validate only part of a form, you must split it into multiple forms, and have the "Save" button "submit" the form. The Wizard Example does this, collecting the form values from each "page" in a parent component.

Hope this helps...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM