Search code examples
reactjsformsreduxmaterial-uisubmit

How to submit the form in stepper


I am trying to submit my form on material ui's stepper form. For more information about it: https://material-ui.com/components/steppers/

Anyway, in my checkout page, I defined the material ui stepper and it has different kind of components which have their own form.

  function getStepContent(step, props) {
      
      switch (step) {
        case 0:
          return <Component1 {...props} />;
        case 1:
          return <Component2 {...props}/>;
        case 2:
        default:
          return "Unknown step";
      }
    }

For example, component1 has its own form and when you click next you go to component2 which has a different kind of form. Component2's form is created with the information coming from Component1's form that's why I need to submit the form before I go to the next. But since I need to submit the form inside the component I am really confused. And of course, I tried to add type="submit" to the Next button but didn't affect anything.

So basically here also, the stepper is defined how to go to the next steps:

<Container>
        <div className={classes.root}>
          <Stepper activeStep={activeStep} orientation="vertical">
            {steps.map((label, index) => (
              <Step key={label}>
                <StepLabel>{label}</StepLabel>
                <StepContent>
                  <Typography>{getStepContent(index, {checkoutForm, handleChange})}</Typography>
                  <div className={classes.actionsContainer}>
                    <div>
                      <Button
                        disabled={activeStep === 0}
                        onClick={handleBack}
                        className={classes.button}
                      >
                        Back
                      </Button>
                      <Button
                        variant="contained"
                        color="primary"
                        onClick={handleNext}
                        className={classes.button}
                      >
                        {activeStep === steps.length - 1 ? "Finish" : "Next"}
                      </Button>
                    </div>
                  </div>
                </StepContent>
              </Step>
            ))}
          </Stepper>
        </div>
      </Container>

So I think I have to do something to submit the form of the component in here:

const handleNext = () => {
    setActiveStep((prevActiveStep) => prevActiveStep + 1);
  };

So I am waiting for your answers. Thanks...


Solution

  • If you want to submit the form with a button outside the form then the button needs the form attribute with the id of the form

    <button type="submit" form={`form-step${activeStep}`} value="Submit">Submit</button>
    

    then the function you passed to the form onSubmit will be executed. So you could pass the handleNext to the form and make sure the form id matches the form attribute off the button

    for example for the form in component 1 create a handleFormSubmit function. then do something with the formdata before you change the activeStep

    const handleFormSubmit = () => {
      // do something with form data
      props.handleNext()
    } 
    
    <form id="form-step1" onSubmit={handleFormSubmit}></form>
    
    

    your example with my changes

    <Container>
            <div className={classes.root}>
              <Stepper activeStep={activeStep} orientation="vertical">
                {steps.map((label, index) => (
                  <Step key={label}>
                    <StepLabel>{label}</StepLabel>
                    <StepContent>
    // pass handleNext to getStepContent here
                      <Typography>{getStepContent(index, {checkoutForm, handleChange, handleNext})}</Typography>
                      <div className={classes.actionsContainer}>
                        <div>
                          <Button
                            disabled={activeStep === 0}
                            onClick={handleBack}
                            className={classes.button}
                          >
                            Back
                          </Button>
                          <Button
                            variant="contained"
                            color="primary"
    // set type submit and form here
                            type="submit"
                            form={`form-step${activeStep}`}
                            className={classes.button}
                          >
                            {activeStep === steps.length - 1 ? "Finish" : "Next"}
                          </Button>
                        </div>
                      </div>
                    </StepContent>
                  </Step>
                ))}
              </Stepper>
            </div>
          </Container>