Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose validate all atoms method for atomWithFormControls #34

Open
Marko-Matijevic opened this issue Nov 7, 2024 · 7 comments
Open

Comments

@Marko-Matijevic
Copy link

Hello,

Is it possible to expose onSubmit button for atomWithFormControls? Because we want to trigger validation for all form fields. Right now we are passing through all form fields and we set touched to true. Because if the field is not touched, it will not be validated.

Can this be implemented? Or do you maybe have a suggestion how to approach this?

Thanks

@barelyhuman
Copy link
Collaborator

I don't think I understand the requirement completely.

You want the atomWithFormControls to expose a handleOnSubmit function so that you can trigger validation for all the fields?

A few questions so I understand the requirement more.

  1. You wish to have validations run as soon as the form mounts?
  2. You are currently using the handleFocus function to trigger the validations?

Is that the right understanding ?

@Marko-Matijevic
Copy link
Author

Hello barelyhuman,

Yes, I would like to have an onSubmit function for triggering validation of all the fields.

  1. No, it is only necessary when the "onSubmit" is triggered.
  2. Right now we are using a "custom" onSubmit method which is going through all of the form items and using "setTouched" we are triggering validation inside items.

carbon

@barelyhuman
Copy link
Collaborator

Oh okay, I'm assuming that you wish to do one of 2 things and i've created examples for the same.

https://github.com/barelyhuman/jotai-form-control-example

Please check them out and let me know if that is the result you wish to achieve or not.

@barelyhuman
Copy link
Collaborator

barelyhuman commented Nov 18, 2024

@Marko-Matijevic
Please close the issue if the above solves for your use case

@Marko-Matijevic
Copy link
Author

Hello again, sorry for the late response. I have created a repo where I show the example https://github.com/Marko-Matijevic/jotai-form-control-example.

So we have validation:

  • when item inside the form is changed we are triggering the validation
  • when we press "submit" button we are triggering the validation for all fields.

The errors should not appear when we are mounting the component. Only in above cases mentioned.

@barelyhuman
Copy link
Collaborator

barelyhuman commented Nov 18, 2024

Any specific reason why you aren't using the onFocus and onBlur event handlers?

@barelyhuman
Copy link
Collaborator

barelyhuman commented Nov 18, 2024

Cause the change's you've made can be handled with the handlers provided by atom and you need to only maintain the state of submission for the errors to show up, here's the code for it and a screencast of it handling cases mentioned by you.

import { useAtom, useAtomValue, atom } from "jotai";
import { atomWithFormControls, atomWithValidate } from "jotai-form";
import { useState } from "react";
import { z } from "zod";

const name = atomWithValidate("", {
  validate: (v) =>
    z.string().min(1, { message: "Name cannot be empty" }).parse(v),
});
const age = atomWithValidate(17, {
  validate: (v) => z.coerce.number(v).min(18).parse(v),
});
const form = atomWithFormControls(
  { name, age },
  {
    validate: (v) => {
      z.object({
        name: z.string().optional(),
      }).parse(v);
    },
  }
);

export const FormTwo = () => {
  const {
    isValid,
    handleOnChange,
    values,
    touched,
    handleOnFocus,
    handleOnBlur,
    fieldErrors,
  } = useAtomValue(form);
  const [submitted, setSubmitted] = useState(false);

  const onSubmit = (e) => {
    e.preventDefault();
    setSubmitted(true);
    if (!isValid) return;
  };

  return (
    <>
      <h2>
        Default values might not exist and need changes and touched state before
        submitting
      </h2>
      <form onSubmit={onSubmit}>
        <div>
          <label>
            <input
              name="name"
              placeholder="name"
              value={values.email}
              onChange={(e) => handleOnChange("name")(e.target.value)}
              onFocus={(e) => handleOnFocus("name")()}
              onBlur={(e) => handleOnBlur("name")()}
            />
            <small>
              {(submitted || touched.name) && fieldErrors?.name?.message}
            </small>
          </label>
        </div>
        <div>
          <label>
            <input
              type="number"
              name="age"
              placeholder="age"
              value={values.age}
              onChange={(e) => handleOnChange("age")(e.target.value)}
              onFocus={(e) => handleOnFocus("age")()}
              onBlur={(e) => handleOnBlur("age")()}
            />
            <small>
              {(submitted || touched.age) && fieldErrors?.age?.message}
            </small>
          </label>
        </div>
        <button onClick={onSubmit}>Submit</button>
      </form>
    </>
  );
};
Screen.Recording.2024-11-18.at.10.19.04.PM.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants