Increment step on condition

Hi everyone,

I want to implement a Form Wizard with MUI Stepper, but I need the step to automatically increment once the form is valid, as it will contain only boolean values. My goal is to show a lot of images to users and expect them to tell if they like it or not.

I was wondering if there’s a way to do this. I’m trying using MaterialArrayControlRenderer.tsx but I don’t find any way to hook into the onChange callback. My idea was too increment the step when the data at step i doesn’t have error.

Basically I’m at this point. I’m able to show the image and go next/back, but I didn’t find a way to change step on change. Any idea?

function MaterialArrayProgressStepperRenderer(props: ArrayLayoutProps) {
    const theme = useTheme();
    const [activeStep, setActiveStep] = React.useState(0);
  
    const handleNext = () => {
      setActiveStep((prevActiveStep) => prevActiveStep + 1);
    };
  
    const handleBack = () => {
      setActiveStep((prevActiveStep) => prevActiveStep - 1);
    };

    
    const { schema: { properties } } = props;
    const numSteps = Object.keys(properties || {}).length ;

    return (
        <>
        <TableRows
            activeStep={activeStep}
            {...props}
          />
        <MobileStepper
          variant="progress"
          steps={numSteps}
          position="static"
          activeStep={activeStep}
          sx={{ maxWidth: 400, flexGrow: 1 }}
          nextButton={
            <Button size="small" onClick={handleNext} disabled={activeStep === numSteps - 1}>
              Next
              {theme.direction === 'rtl' ? (
                <KeyboardArrowLeft />
              ) : (
                <KeyboardArrowRight />
              )}
            </Button>
          }
          backButton={
            <Button size="small" onClick={handleBack} disabled={activeStep === 0}>
              {theme.direction === 'rtl' ? (
                <KeyboardArrowRight />
              ) : (
                <KeyboardArrowLeft />
              )}
              Back
            </Button>
          }
        />
        </>
    );
  }

export const materialArrayStepperTester: RankedTester = rankWith(
    6,
    or(isObjectArrayControl, isPrimitiveArrayControl)
);
  
export default withJsonFormsArrayLayoutProps(MaterialArrayProgressStepperRenderer);

Hi @paulSerre,

For this use case we usually recommend to not implement this within JSON Forms, but use JSON Forms to accomplish it.

What I mean is that the stepper is ideally implemented outside of JSON Forms, then each “step” is rendered via a different JSON Schema / UI Schema. This way it’s very straightforward to determine whether the form is valid, etc.

When you implement this as a custom renderer you need to basically implement the same logic anyway, however you also need to know how to use the JSON Forms internal API. So if possible, I would recommend the first approach.


In case you still want to go the custom renderer route, then you need to use JsonFormsDispatch in your renderer to dispatch to each specific step’s UI. You can inspect the form-wide errors to detect whether the dispatched to step has any errors, if not, you can dispatch to a different one. You can do that via useEffect on the data and/or calculated errors.

Thank you. I did as you said, i.e render different JsonForms in each MUI Stepper and it works fine.

1 Like