Form validation in Stepped Container

I have a stepped container with a form in each step with the header, footers and submit button hidden in each form.

I would like to validate the form when progressing to the next step and cancel navigation when validation fails.

However, when i call "form.validate()" and subsequently check "form.invalid" to conditionally navigate the invalid property is always false. I have also tried adding the await modifier but it does not help. So the "form.validate()" method is not await, its returns immediately.

Is this a bug or is there a better way to handle validation per step?

As a work-around, using setTimeout to check the "form.invalid" property with a timeout of 500ms seems to do the trick, just make sure to await the call to "form.validate()" first.

Hi @cumminsj :slight_smile:

As a quick workaround, would adding some logic to the "Disabled" field of the next button work?

In this example, I am disabling the button if we're at the end of the container (default behavior) OR if the form is invalid by checking the form1.invalid property.

{{ steppedContainer1.currentViewIndex + 1 === steppedContainer1.viewKeys.length || form1.invalid }}

Hi @victoria

Thanks for the reply.

The problem with this solution is that I have the submit buttons are hidden because I want to trigger the validation when the next button is clicked.

I then collect all the forms data at the end of the steps and save it.

Oh, no worries at all. In my example, I've actually disabled the container "Next" button in my screenshot.

I've also hidden the form submit button if the form is invalid.

Hi @cumminsj @victoria,

Have you found a better solution than using a timeout?

I am building the exact same flow as you are, and running into the same issue. Here's the query that is triggered when I click the Next button in the steppedContainer

switch (steppedContainer1.currentViewIndex) {
  case 0:
    await form.validate()
    if (form.invalid) {
      console.log("invalid form")
      break;
    }
    showNextStep()
    break;

No matter if I await, not await or even do const isValid = await form.validate() and use that variable going forward, the validate() call does not seem to be awaited.

Disabling the Next button in the steppedContainer is not a good solution because I need some mechanism to validate the form before proceeding to the next step.

I have some 4 forms that need to be filled out and validated, and they are all submitted in the last step.

I have come up with a solution, although I still don't understand why my previous approach wouldn't work.

Here's the code that works.

query1 that is trigger on each "Next" button click in the steppedContainer

function showNextStep() {
	steppedContainer1.setCurrentViewIndex(steppedContainer1.currentViewIndex + 1);
}

async function nextStepper() {
	switch (steppedContainer1.currentViewIndex) {
		case 0:
            const isform1FormValid = await validateForm.trigger({additionalScope: {form: formCreateInstallerCompany}})
			if (!isform1FormValid) {
				break;
			}
			showNextStep();
			break;
	}
}

nextStepper()

and the validateForm query that is triggered when a form need to be validated in order to proceed

const x = await form.validate()

return x

Hi @tomasvemola! Definitely strange why your code didn't work/properly await. Is the promises section in this guide close to what you were trying to do? Glad to hear you were able to find a solution in the meantime, though. :pray:

heyyy there I've faced this same issue
I fixed it by using a combination of the above solutions
just run this script when the user clicks the next button
this will guarantee that you won't move to the next tab unless the form is valid

additionally you can:

  • disable next button using the form.invalid
  • add notification for users to know why the next button didn't work

const isValid =  await create_talent_form.validate();
if(isValid) steppedContainer1.showNextVisibleView()
2 Likes

Has anyone tried to do this with the Wizard component? It feels more flexible than the stepped container, so I'm wondering if it's better and I should switch