Trying to build a factory class for Formik and Yup. Therefore I would like to build up the Yup validation method chain, but I failed... :(

Viewed 22

The plan is I give to this factory class an array of objects, and that gives me beck a Formik config with filled Yup validation. After then the getFrom method of my factory class generates the entire form also that can I directly rendering now with react.

But I doen't know any method to solve that for example Yup.string().required().max(2, "error") method chain built up in my class.

Plases give me some direction where can I find solutions for this problem.

// this the form describing array of objects:
const exampleFields = [
  {
    name: "First name",
    inputType: "text",
    valueType: "string",
    label: "Enter your first name",
    initialValue: "",
    placeholder: "Enter first name here...",
    stylingClasses: {
      inputCotanierClasses: "w-100",
      labelClasses: "text-left",
      inputClassess: "border-0 border-bottom border-dark",
      errorClasses: "text-danger",
    },
    validation: {
      required: { message: "First name is required" },
      min: {
        value: 2,
        message: "First name must be at least 2 characters",
      },
      max: {
        value: 15,
        message: "first name must be at most 15 characters",
      },
    },
  },
  {
    name: "Last name",
    inputType: "number",
    valueType: "number",
    label: "Enter your last name",
    initialValue: "",
    placeholder: "Enter last name here...",
    validation: {
      required: { message: "Last name is required" },
      min: {
        value: 2,
        message: "Last name must be at least 2 characters",
      },
      max: {
        value: 10,
        message: "Last name must be at most 10 characters",
      },
    },
  },
  {
    name: "email",
    inputType: "text",
    valueType: "email",
    label: "Enter your email",
    initialValue: "",
    placeholder: "Enter yout emial here...",
    validation: {
      required: { message: "Email is required" },
      email: true,
    },
  },
];

//and this is my factory class:
import React from "react";
import * as Yup from "yup";

export default class FormFactory {
  constructor(fields, submit, Yup) {
    this.submit = submit;

    const buildUpValidation = (Yup, validation, { message, value }) => {
      return Yup[validation](message, value);
    };

    fields.forEach((field) => {
      const initialYup = Yup[field.valueType]();
      const validations = Object.entries(field.validation);
      validations.forEach((validation) => {
        const [validationType, params] = validation;
        console.log(validationType, params);
        buildUpValidation(initialYup, validationType, params || true);
      });
    });

    //this.validationSchema = Yup.object().shape({});
    //console.log(this.validationSchema);
  }

  getConfig() {
    return {
      initialValues: this.initialValues,
      validationSchema: this.validationSchema,
      onSubmit: (values) => this.submit(values),
    };
  }

  generateField(
    formik,
    { label, id, name, key, inputType, placeholder, stylingClasses }
  ) {
    return (
      <div
        key={key}
        className={`input-container ${stylingClasses?.inputCotanierClasses &&  stylingClasses.inputCotanierClasses}`
        }
      >
        {label && (
          <label
            className={
              stylingClasses?.labelClasses && stylingClasses.labelClasses
            }
            htmlFor={id || name}
          >
            {label}
          </label>
        )}
        <input
          id={id || name}
          className={
            stylingClasses?.inputClassess && stylingClasses.inputClassess
          }
          name={name || id}
          type={inputType || "text"}
          value={formik.values[name || id]}
          placeholder={placeholder}
          onBlur={formik.handleBlur}
          onChange={formik.handleChange}
        />
        <>
          {formik.touched[name || id] && formik.errors[name || id] ? (
            <p
              className={
                stylingClasses.errorClasses && stylingClasses.errorClasses
              }
            >
              {formik.errors[name || id]}
            </p>
          ) : null}
        </>
      </div>
    );
  }

  getForm(formik) {
    return this.fields.map((field, key) =>
      this.generateField(formik, { ...field, key })
    );
  }
}

//and the usage is the followings:
import React from "react";
import { useFormik } from "formik";
import FormFactory from "./FormFactory";

const SignUpFormikFactory = () => {
  const singUpForm = new FormFactory(exampleFields, (values) =>
    console.log(values)
  );

  // console.log(singUpForm.getConfig());

  const formik = useFormik({ ...singUpForm.getConfig() });

  // console.table("| formik.values", formik.values);
  // console.table("| formik.errors", formik.errors);
  // console.table("| formik.touched", formik.touched);

  return (
    <form onSubmit={formik.handleSubmit}>
      <div className="form-container">
        {singUpForm.getForm(formik)}
        <button type="submit">Submit</button>
      </div>
    </form>
  );
};

export default SignUpFormikFactory;

/*********************/
/* And in the app is */
/*********************/
import "./App.css";
import SignUp from "./SignUp";
import SignUpFormik from "./SignUpFormik";
import SignUpFormikFactory from "./SignUpFormikFactory";

function App() {
  return (
    <div className="App">
      <SignUpFormikFactory />
    </div>
  );
}

export default App;

0 Answers
Related