admin管理员组

文章数量:1287627

I have a multi-step form, which I am making using react, to work on validation I am using react-hook-form.

I have already achieved 90% of things just one thing I am facing the issue is getting the second form data which is dynamic.

What I am doing is

  • In my first form I have two fields when those are filled (validated) I am going to the next form
  • In my next form I have two input fields and on the add button user can add multiple rows of fields as well and these are working fine

issue

  • Now when I create new fields in the second form I want to validate them but not getting an idea how can I do that.

What I have done

In my main ponent, I am doing this for validation

const forms = [
  {
    fields: ['desig', 'dept'],
    ponent: () => (
      <Pro register={register} errors={errors} defaultValues={defaultValues} />
    ),
  },
  {
    fields: [
      `userInfo[0].fname`, // here I am facing issue if I am statically putting 0,1 then it is validating that perticular form
      `userInfo[0].sirname`,
    ],
    ponent: () => (
      <Basic
        register={register}
        errors={errors}
        defaultValues={defaultValues}
        inputHolder={inputHolder}
        deleteRow={deleteRow}
        addRow={addRow}
      />
    ),
  },
];

On click of submitting, I am doing this

const handleSubmit = (e) => {
  triggerValidation(forms[currentForm].fields).then((valid) => {
    if (valid) {
      console.log('whole form data - ', JSON.stringify(defaultValues));
    }
  });
};

and here i want data as like below if two data is added in form2

    {
  "fname": "dsteve",
  "sname": "smith",
  "userInfo": [
    {
      "desig": "ddd",
      "dept": "deptee"
    },
    {
      "desig": "ddd",
      "dept": "deptee"
    }
  ]
}

I have done everything but here only I have been stuck, I know where the issue is

Instead of this

fields: ["fname", "sname"],

I have to do like this

fields:[`userInfo[0].name, `userInfo[0].sname],

This 0-1 I have to make dynamic as per indexes, I don't know what I am missing

I tried mapping the fields with index through inputHolderbut it did not work

Edit / Update

If I am doing like this

fields:[`userInfo[0].name`,`userInfo[1].name`, `userInfo[0].sname`,`userInfo[1].sname],

So it is taking validation for two fields, but that is manually I am doming, if user creates more fields then that should take these fields dynamically.

Here is my code sandbox, which contains the full code

Here is my code sandbox

I am open to use any new approach but that should use react-hook-form and full fill what I am trying to do

I don't know how to progrees with my approach now

I have a multi-step form, which I am making using react, to work on validation I am using react-hook-form.

I have already achieved 90% of things just one thing I am facing the issue is getting the second form data which is dynamic.

What I am doing is

  • In my first form I have two fields when those are filled (validated) I am going to the next form
  • In my next form I have two input fields and on the add button user can add multiple rows of fields as well and these are working fine

issue

  • Now when I create new fields in the second form I want to validate them but not getting an idea how can I do that.

What I have done

In my main ponent, I am doing this for validation

const forms = [
  {
    fields: ['desig', 'dept'],
    ponent: () => (
      <Pro register={register} errors={errors} defaultValues={defaultValues} />
    ),
  },
  {
    fields: [
      `userInfo[0].fname`, // here I am facing issue if I am statically putting 0,1 then it is validating that perticular form
      `userInfo[0].sirname`,
    ],
    ponent: () => (
      <Basic
        register={register}
        errors={errors}
        defaultValues={defaultValues}
        inputHolder={inputHolder}
        deleteRow={deleteRow}
        addRow={addRow}
      />
    ),
  },
];

On click of submitting, I am doing this

const handleSubmit = (e) => {
  triggerValidation(forms[currentForm].fields).then((valid) => {
    if (valid) {
      console.log('whole form data - ', JSON.stringify(defaultValues));
    }
  });
};

and here i want data as like below if two data is added in form2

    {
  "fname": "dsteve",
  "sname": "smith",
  "userInfo": [
    {
      "desig": "ddd",
      "dept": "deptee"
    },
    {
      "desig": "ddd",
      "dept": "deptee"
    }
  ]
}

I have done everything but here only I have been stuck, I know where the issue is

Instead of this

fields: ["fname", "sname"],

I have to do like this

fields:[`userInfo[0].name, `userInfo[0].sname],

This 0-1 I have to make dynamic as per indexes, I don't know what I am missing

I tried mapping the fields with index through inputHolderbut it did not work

Edit / Update

If I am doing like this

fields:[`userInfo[0].name`,`userInfo[1].name`, `userInfo[0].sname`,`userInfo[1].sname],

So it is taking validation for two fields, but that is manually I am doming, if user creates more fields then that should take these fields dynamically.

Here is my code sandbox, which contains the full code

Here is my code sandbox

I am open to use any new approach but that should use react-hook-form and full fill what I am trying to do

I don't know how to progrees with my approach now

Share Improve this question edited Dec 2, 2020 at 0:25 manish thakur asked Oct 7, 2020 at 9:28 manish thakurmanish thakur 82010 gold badges43 silver badges82 bronze badges 8
  • You should add the whole ponent like this question here so others people can help you more quickly. – NearHuscarl Commented Oct 7, 2020 at 11:40
  • @NearHuscarl hey in above link you are not doing validation, I think that is the main point whereI have been stuck. – manish thakur Commented Oct 8, 2020 at 4:04
  • My point is, there is not enough context for me to start debugging your code. – NearHuscarl Commented Oct 8, 2020 at 4:21
  • @NearHuscarl Hey I have edited my post by adding code sandbox link please do check – manish thakur Commented Oct 8, 2020 at 4:55
  • I'm just starting to play with this. I think it will bee more obvious what's going on if I break in into a few ponents instead of one. But one potentially issue that I noticed already is that there's no way to remove a row once it's been added. – Linda Paiste Commented Oct 15, 2020 at 3:25
 |  Show 3 more ments

2 Answers 2

Reset to default 4

You can create an array of 2 empty strings where first one represents first row F name,and second one represents first row S Name under yours inputHolder in the MainComponent:

 const [inputHolder, setinputHolder] = useState([
    {
      id: 1,
      fname: "",
      sname: ""
    }
  ]);
  const [names, setNames] = useState(["", ""]);

Next,every time the user ads a new row you add to empty strings in names array.

 const addRow = () => {
    console.log(inputHolder.length);
    let item = {
      id: inputHolder.length + 1,
      fname: "",
      sname: ""
    };
    setinputHolder([...inputHolder, item]);
    setNames([...names, "", ""]);
   
  };

Where each empty string represents F name and S name. Finally,fields is set to names in second form:

fields: names,
      ponent: (register, errors, defaultValues) => (
        <Form2
          register={register}
          errors={errors}
          defaultValues={defaultValues}
          inputHolder={inputHolder}
          addRow={addRow}
        />

I remend you to use yup as a validation utils. It is a powerful tool.

  1. Create two schemes for both of forms:
 import * as yup rom 'yup';
    
 const schema = yup.object().shape({
   field1: yup.string().required() // number, array - whatever,
   field2: yup.string().required(),
 })

Similar schema should be created for second form as well

  1. Create first form and apply your validators by resolver
import { yupResolver } from '@hookform/resolvers/yup';

const { register, handleSubmit } = useForm({
  resolver: yupResolver(schema),
});
  1. Do the same for your second form - useForm + validation resolver.

  2. next part is to make your second form being dynamic, so do use hook useFieldArray

const { fields, append, remove } = useFieldArray({
  name: 'userInfo', *// key, a part of path to access your fields - userInfo[n].fname*
  control: form.control, *// to connect you fields to basic form* 
});
  1. Now you can create actions*(buttons/links)* and pass them {append, remove} actions.

  2. {fields} should be rendered by .map as default. once you will try to validate your second form with (n) count off section - your schema would be applied to each of sections.

there is another solution, you can skip part with second form(I would prefer this way if your second schema could be massive).

you can connect your useFieldArray fields to first form, and your single validation schema looks like:

 import * as yup rom 'yup';
    
 const infoSchema = yup.object().schema({
   firstName: yup.string(),
   lastName: yup.string(),
 })

 *// enhance infoSchema to your expected logic.* 

 const schema = yup.object().shape({
   field1: yup.string().required() // number, array - whatever,
   field2: yup.string().required(),
   userInfo: yup.array().of(infoSchema),
 })

本文标签: javascriptHow to validate multistep form in reactStack Overflow