View on GitHub

React Hook Form Plus

(RHF+)

Imperative Form Submission

Purpose

This feature allows for the imperative submission of forms, meaning you can trigger form submission programmatically from anywhere in your application, even outside the form context.

Benefits

API Changes

Property updates

export type UseFormProps<...> = Partial<{
    // ... existing properties
    id: string; // New property
}>;
export type UseFormReturn<...> = {
    // ... existing properties
    id: string; // New property
    submit: () => void; // New method
};

Description

Now all forms returned by any RHF API contain an id and submit function. You may assign a custom unique ID to each form using the id option in the useForm hook. If no ID is given, a random one is generated. Using the form.submit() method you can submit the form imperatively. This is useful when you want to trigger form submission from anywhere in your application (including outside the Form context).

Behavior

The submit() method programmatically triggers form submission using the same validation and submission flow as if the user submitted the form normally. The method will:

  1. Validate all form fields according to their validation rules
  2. If validation passes, call the onSubmit handler
  3. If validation fails, populate form errors and prevent submission
  4. Work correctly with all form validation modes and configurations

Examples

Basic Imperative Submission

// Example using the useForm hook
import { useForm } from '@bombillazo/rhf-plus';

function App() {
  const form = useForm({
    id: 'my-form', // uniquely identify the form (optional)
  });

  return (
    <>
      <form
        id={form.id} // assign the form ID to the form element
        onSubmit={form.handleSubmit((data) => console.log(data))}
      >
        <input {...form.register('name')} />
      </form>
      {/* imperatively submit the form */}
      <Button onClick={() => form.submit()}>Submit</Button>
    </>
  );
}

With Form Context

// Example with Form Context
import { useForm, FormProvider, useFormContext } from '@bombillazo/rhf-plus';

function App() {
  const form = useForm();

  return (
    <FormProvider {...form}>
      <form
        id={form.id}
        onSubmit={form.handleSubmit((data) => console.log(data))}
      >
        <input {...form.register('name')} />
      </form>
      <SubmitButton />
    </FormProvider>
  );
}

function SubmitButton() {
  const form = useFormContext();

  return <Button onClick={() => form.submit()}>Submit</Button>;
}

With Form Control

// Example using Form Control
import { useForm, createFormControl } from '@bombillazo/rhf-plus';

const fc = createFormControl();

function App() {
  useForm({ formControl: fc.formControl });

  const name = fc.watch('name');

  useEffect(() => {
    if (name === '1234') {
      // imperatively submit the form
      fc.submit();
    }
  }, [name]);

  return (
    <form id={fc.id} onSubmit={fc.handleSubmit((data) => console.log(data))}>
      <input {...fc.register('code')} />
    </form>
  );
}

Limitations

Backward Compatibility

This feature is fully backward compatible. The id and submit properties are automatically added to all forms without breaking existing implementations.