score:0

here's one approach,

const validation_map = dynamic_forms.reduce((acc, current) => {
  current.inputs?.foreach((input) => {
    acc[input.name] = input.validation;
  });

  return acc;
}, {});

const validate = (input, validation) => {
  const inputlength = input.length;
  const { required, minlength, maxlength } = validation;

  return (
    (required && !inputlength) ||
    (!isnan(minlength) && inputlength < minlength) ||
    (!isnan(maxlength) && inputlength > maxlength)
  );
};

export default function app() {
  const [formvalues, setformvalues] = usestate({});

  const updateformvalue = (name, value) => {
    setformvalues((prev) => ({ ...prev, [name]: value }));
  };

  const handleinputchange = (event) => {
    const { name, value } = event.target;
    updateformvalue(name, { value });
  };

  const handlesubmit = () => {
    setformvalues((prev) => {
      const updatedvalues = { ...prev };
      object.entries(validation_map).foreach(([name, validation]) => {
        const input = formvalues[name]?.value || "";

        updatedvalues[name] = {
          value: input,
          hasvalidationerror: validate(input, validation)
        };
      });

      return updatedvalues;
    });
  };

  const handleinputblur = (event) => {
    const { name, value } = event.target;
    updateformvalue(name, {
      value,
      hasvalidationerror: validate(value, validation_map[name])
    });
  };

  return (
    <div>
      <form autocomplete="off">
        {dynamic_forms.map((item) => (
          <div key={item.texts.header}>
            <h3>{item.texts.header}</h3>
            {item.inputs && (
              <>
                {item.inputs.map((eachinput) => {
                  const { label, name, type, validation, error } = eachinput;
                  const { value, hasvalidationerror } = formvalues[name] || {};
                  return (
                    <div key={label}>
                      <label>{label}</label>
                      <input
                        style={{
                          border: hasvalidationerror ? "1px red solid" : "solid"
                        }}
                        {...validation}
                        type={type}
                        onblur={handleinputblur}
                        value={value || ""}
                        name={name}
                        onchange={handleinputchange}
                      />
                      {hasvalidationerror && (
                        <div style={{ color: "red" }}>{error}</div>
                      )}
                    </div>
                  );
                })}
              </>
            )}
          </div>
        ))}
        <button onclick={handlesubmit}>submit</button>
      </form>
    </div>
  );
}

i did not quite understand the error field for each input, isn't it supposed to be different for each validation? for example, if the password is not provided error can be "password is required", but if it's provided and it does not meet the min length requirement then the error should be something like "password should have minimum x characters". since only a generic error message is given for each input, i have only displayed that in case of a validation error. if you want to show different messages for different cases, instead of having the boolean hasvalidationerror in state ,you can use a string errormessage and have the function validate return the required error message


Related Query

More Query from same tag