šŸ“ Sign Up | šŸ” Log In

← Root | ↑ Up

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” │ šŸ“„ shadcn/directory/wandrydev/wandry-ui/wandry-inertia-form │ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

╔══════════════════════════════════════════════════════════════════════════════════════════════╗
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘

title: Wandry Inertia Form description: A simple way to create forms for Inertia applications.

A simple way to create forms for Inertia applications.

<Image src="/images/form.png" width="1432" height="960" alt="VS" className="border" />

Project Goal

Simplify form development in Inertia.js/React applications. Of course, Inertia.js has its own useForm and Form component, but it doesn't provide as many capabilities that everyone is used to when using react-hook-form.
We've made it so that anyone who has used react-hook-form can immediately use our library without studying the documentation from cover to cover.

What we offer:

  • form value tracking with useWatch
  • getting field values anywhere in the code with getValues()
  • adding values to the form with setValue()
  • simpler and more flexible form key management, support for nested keys as a regular string user.info.name
  • creating custom fields with Field or useField components

How it's implemented

The root point is the Form component, which implements a wrapper over useForm from inertia.js and creates a React.Context that wraps all form state and the ability to manipulate it. That's it. All you need to do is call the <Form> component and all child components will already be able to work with your form.

Installation

<CodeBlockCommand __pnpm__="pnpm add @wandry/inertia-form" __npm__="npm install @wandry/inertia-form" __bun__="bun install @wandry/inertia-form" __yarn__="yarn add @wandry/inertia-form" />

Components and Hooks

Form

Usage Example:

<Form
  action="/api/submit"
  method="post"
  defaultValues={{ name: "" }}
  onSubmit={(values) => console.log(values)}
>
  {/* form fields */}
</Form>

| Prop | Type | Required | Description | | ------------------- | ---------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------ | | action | string | Yes | URL or form action object. | | id | string | No | HTML id for the form. | | method | "get" | "post" | "put" | "patch" | "delete" | No | HTTP method for form submission. Default is "post". | | defaultValues | Record<string, any> | No | Initial values for form fields. | | options | FormOptions | No | Options for form submission (except data). | | className | string | No | CSS class for the form. | | validationSchema | any | No | Validation schema (e.g., for Yup). | | validator | ValidationAdapter | No | Custom validation adapter. | | sharedProps | Record<string, any> | No | Shared props that will be available to all form fields. | | preventFormAction | boolean | No | If true, prevents default form behavior on submission. | | onSubmit | (value: any) => void | No | Callback called when the form is submitted. | | useWayfinder | boolean | No | Whether to use Wayfinder mode for form submission. | | ...FormAttrs | HTMLAttributes<HTMLFormElement> (without defaultValue, onSubmit) | No | Any other standard HTML form attributes, except defaultValue and onSubmit. |

Field

Usage Example:

<Field
  name="email"
  controller={({ value, onChange, error }) => (
    <div>
      <input
        type="email"
        value={value}
        onChange={(e) => onChange(e.target.value)}
        placeholder="Enter email"
      />
      {error && <span style={{ color: "red" }}>{error}</span>}
    </div>
  )}
/>

| Prop | Type | Required | Description | | -------------- | ------------------------------------------------------- | -------- | --------------------------------------------------------------- | | id | string | No | HTML id for the field. | | name | string | Yes | Field name (key in the form). | | controller | (field: FieldControllerProps<TValue>) => ReactElement | Yes | Controller function that returns a React element for the field. | | defaultValue | FieldValue | No | Initial field value. |

FieldControllerProps is passed to controller:

| Prop | Type | Required | Description | | ---------- | ------------------------- | -------- | ------------------------------ | | onChange | (value: TValue) => void | Yes | Value change handler. | | value | TValue | Yes | Current field value. | | error | string | No | Error message (if any). | | disabled | boolean | No | Whether the field is disabled. |

useField

Usage Example:

const { value, onChange, error } = useField("username", { defaultValue: "" });

return (
  <div>
    <input
      value={value}
      onChange={(e) => onChange(e.target.value)}
      placeholder="Enter username"
    />
    {error && <span style={{ color: "red" }}>{error}</span>}
  </div>
);

| Return Value | Type | Description | | ------------ | ----------------------------- | ------------------------------------- | | value | FieldValue | Current field value. | | onChange | (value: FieldValue) => void | Function for updating field value. | | error | string | undefined | Error message for the field (if any). |

Parameters:

| Parameter | Type | Required | Description | | --------- | ------------------------ | -------- | ----------------------------------- | | name | string | Yes | Field name (key in the form). | | options | { defaultValue?: any } | No | Options, e.g., initial field value. |

useFormContext

Note: The useFormContext hook should only be used inside the Form component.

Usage Example:

const { getValues, setValue, form } = useFormContext();

// Get all form values
const allValues = getValues();

// Get a specific field value
const email = getValues("email");

// Set field value
setValue("username", "newUser");

| Return Value | Type | Description | | ------------ | -------------------------------------------- | --------------------------------------------------------- | | form | FormContextType | Form context, includes state and form management methods. | | getValues | (name?: string, defaultValue?: any) => any | Get all form values or a specific field value by name. | | setValue | (name: string, value: any) => void | Set field value by name. |

useWatch

A hook for tracking changes to form values or a specific field in real-time.

Usage Example:

import { useWatch } from "@wandry/inertia-form";

function ProfileForm() {
  const username = useWatch("username");
  const allValues = useWatch();

  return (
    <div>
      <div>Username: {username}</div>
      <pre>{JSON.stringify(allValues, null, 2)}</pre>
    </div>
  );
}

| Name | Type | Required | Description | | --------- | ------------------------ | -------- | ----------------------------------------------------------------- | | name | string | No | Field name to track (nested keys are supported via dot notation). | | options | { defaultValue?: any } | No | Options, e.g., default value if the field is missing. |

ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•

← Root | ↑ Up