Dynamic Form with Material UI + Formik

412 Views Asked by At

I'm trying to create a dynamic form using material UI + formik fieldArray. What I have is an array of objects called questionList. This questionList will have multiple questions. I want to render my form once, then reset it for the next question etc. Also I will render them as card in the left side that's somewith for later.

Im trying to use FieldArray but apparently I'm doing something wrong. I will give my select example where I change the question Type from Quiz to True/False. The value will change in my questionList but I'm getting this error.

export default function CreateQuizPage() {
  const location = useLocation();
  const { values } = location.state;

  const validationSchema = yup.object().shape({
    questionList: yup
      .array()
      .of(
        yup.object().shape({
          questionType: yup
            .string()
            .oneOf(["Quiz", "True/False"], "Please select a question type")
            .required("Please select a valid question type"),
          pointType: yup
            .string()
            .oneOf(["Standard", "Double"], "Please select a point type")
            .required("Please select a valid point type"),
          answerTime: yup
            .number()
            .oneOf(
              timeToAnswer.map((level) => level),
              "Please select a valid time"
            )
            .required("Please select a valid time"),
          backgroundImage: yup.string(),
          question: yup.string().required("Question is requred"),
          answerList: yup
            .array()
            .of(
              yup.object().shape({
                body: yup.string().required("Required"),
                isCorrect: yup.boolean(),
              })
            )
            .required("Required"),
          questionIndex: yup.number().required("Required"),
        })
      )
      .required("Required"),
  });

  const formik = useFormik({
    initialValues: {
      questionList: [
        {
          questionType: "Quiz",
          pointType: "",
          answerTime: null,
          backgroundImage: "",
          question: "",
          answerList: [
            {
              body: "",
              isCorrect: false,
            },
            {
              body: "",
              isCorrect: false,
            },
            {
              body: "",
              isCorrect: false,
            },
            {
              body: "",
              isCorrect: false,
            },
          ],
          questionIndex: 0,
        },
      ],
    },
    validationSchema: validationSchema,
    onSubmit: (values) => {
      console.log({ values: values });
    },
  });

  useEffect(() => {
    console.log("QuestionList:", formik.values.questionList);
  }, [formik.values.questionList]);

  useEffect(() => {
    console.log("Values:", values);
  });
  return (
    <>
      <form onSubmit={formik.handleSubmit}>
        <FieldArray name="questionList">
          {({ push, remove }) => (
            <>
              <Grid container spacing={10}>
                <Grid xs={3} item>
                  <Box backgroundColor="red">Box1</Box>
                </Grid>
                <Grid xs={6} item>
                  <Box backgroundColor="yellow">Box2</Box>
                </Grid>
                <Grid xs={3} item>
                  {formik.values.questionList.map((question, index) => {
                    console.log(question, index);
                    return (
                      <div key={index}>
                        <InputLabel id={`questionType-${index}`}>
                          Question Type
                        </InputLabel>
                        <FormControl>
                          <Select
                            id={`questionType-${index}`}
                            name={`questionList.${index}.questionType`}
                            value={question.questionType}
                            onChange={formik.handleChange}
                            label={`questionType-${index}`}
                          >
                            <MenuItem key={`Quiz-${index}`} value="Quiz">
                              Quiz
                            </MenuItem>
                            <MenuItem
                              key={`TrueFalse-${index}`}
                              value="True/False"
                            >
                              True/False
                            </MenuItem>
                          </Select>
                          {/* {formik.touched.questionList &&
                            formik.touched.questionList[index] &&
                            formik.touched.questionList[index].questionType &&
                            Boolean(
                              formik.errors.questionList?.[index]?.questionType
                            ) && (
                              <FormHelperText>
                                {
                                  formik.errors.questionList?.[index]
                                    ?.questionType
                                }
                              </FormHelperText>
                            )} */}
                        </FormControl>
                      </div>
                    );
                  })}
                </Grid>
              </Grid>
            </>
          )}
        </FieldArray>
      </form>
    </>
  );
}

enter image description here

0

There are 0 best solutions below