π collection of atoms, utility functions and hooks to easily create forms with jotai and react
Attention! This library is currently under development and may not be fully functional yet! Please check back later for updates! Your patience is appreciated! Thank you for your understanding! π
The docs can be found at https://omnidan.github.io/jotai-advanced-forms/
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>
);
}
See .github/CONTRIBUTING.md
, then .github/DEVELOPMENT.md
.
Thanks! π
π This package was templated with
create-typescript-app
using thecreate
engine.