Skip to content

omnidan/jotai-advanced-forms

Repository files navigation

Jotai Advanced Forms

πŸ“‹ collection of atoms, utility functions and hooks to easily create forms with jotai and react

🀝 Code of Conduct: Kept πŸ§ͺ Coverage πŸ“ License: MIT πŸ“¦ npm version πŸ’ͺ TypeScript: Strict

Documentation

The docs can be found at https://omnidan.github.io/jotai-advanced-forms/

Usage

npm i jotai-advanced-forms

In a directory co-located with the component/page that uses the form, place a state.ts file, with the following contents:

import { createForm } from "jotai-advanced-forms";

const { formFieldAtom, useForm } = createForm();
export { useForm };

// required field
export const firstNameAtom = formFieldAtom<string, "required">({
  initialState: "",
  validate: (value) => {
    if (value.length === 0) return "required";
  },
});

// optional field
export const lastNameAtom = formFieldAtom<string, undefined>({
  initialState: "",
});

Then, it is advisable to create custom input components that can deal with the props that this library provides:

import type { UseFormFieldProps } from "jotai-advanced-forms";

export function StringInput({
  value,
  onChange,
  onBlur,
  ref,
  hasError,
  errorCode,
  errorText,
}: UseFormFieldProps<string>) {
  return (
    <div>
      <input
        value={value}
        onChange={(e) => onChange(e.target.value)}
        onBlur={onBlur}
        ref={ref}
      />
      {hasError && (
        <p>
          {errorText} ({errorCode})
        </p>
      )}
    </div>
  );
}

Now, in a React component that contains the form, you can do the following:

import { useFormField } from "jotai-advanced-forms";
import { firstNameAtom, lastNameAtom, useForm } from "./state.js";
import { StringInput } from "./StringInput.js";

export function NameInputForm() {
  const firstNameField = useFormField({
    atom: firstNameAtom,
    errors: {
      // if you do not specify this, it will cause a type error, forcing you to handle error messages!
      required: "First name is required!",
    },
  });

  const lastNameField = useFormField({
    atom: lastNameAtom,
  });

  const { submitForm, isSubmitting } = useForm({
    onValid: () => alert("success!"),
  });

  function handleSubmit(e) {
    e.preventDefault();
    submitForm();
  }

  return (
    <form onSubmit={handleSubmit}>
      <StringInput {...firstNameField} />
      <StringInput {...lastNameField} />
      <input type="submit" value="Submit" disabled={isSubmitting} />
    </form>
  );
}

Development

See .github/CONTRIBUTING.md, then .github/DEVELOPMENT.md. Thanks! πŸ’–

πŸ’ This package was templated with create-typescript-app using the create engine.

About

πŸ“‹ collection of atoms, utility functions and hooks to easily create forms with jotai and react

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •