API reference
Every public method is listed here, grouped by lifecycle. Most methods are chainable and return the same FormController. Click into the per-method pages of the project repository for the full signature, parameter table and runnable example.
Lifecycle
Section titled “Lifecycle”form(target, options?)— bind a controller to anHTMLFormElement. The main entry point.element— the bound form (fis an alias).reset()— restore native form values and clear errors.destroy()— tear down listeners, observer, and caches.
Registry helpers (vanilla)
Section titled “Registry helpers (vanilla)”browser— module-level singleton that wrapsform()withnewForm/destroyForm/available. Mirrors the IIFE surface without auto-installing a global.browser.newForm— build + register a controller underbrowser.available[id].browser.destroyForm— destroy + unregister a controller by id.browser.available— registry of active controllers keyed by id.
Submission
Section titled “Submission”onSubmit(callback, preventDefault?)— register a submit handler.autoSubmit(options?)— enable submit-on-change with optional debounce.disableAutoSubmit()— turn auto-submit off and cancel pending debounce.
Field observation
Section titled “Field observation”watch(field, callback)— chainable fire-and-forget reaction to a field.observe(field, callback)— likewatch, but returns an unsubscribe function and fires immediately.unwatch(field?, callback?)— remove watched callbacks.subscribe(listener)— react to the entire form state.
Field values
Section titled “Field values”setValue(name, value)— write a value into a field.getValue(name)— read the current value of a field.getField(name)— read the underlying DOM element(s).prefill(fieldName?)— populate the form fromwindow.location.search.format(config)— apply@samline/formatterto a field, with auto-managed raw mirror and cursor tracking.formatAll(config)— alias offormat()forfield: string[]use cases.
Validation
Section titled “Validation”validate(fields?)— run validation, return the result.revalidate(fields?)— alias ofvalidatewith explicit intent.setErrors(fields)— push manual errors.clearErrors(fields?)— clear manual errors.
State and data
Section titled “State and data”getData()— return plain object +FormDatafor the form.getState()— return a snapshot of values, errors, and metadata.append(options)— inject a DOM node into the form.
Pure helpers
Section titled “Pure helpers”These do not require a controller. They accept plain values or a raw HTMLFormElement and return results — safe to tree-shake into any bundle.
parseFormData(formElement)— same serializer used internally, no controller needed.validateValues(values, schema)— run a schema against a values map.validateFieldValue(field, value, rules, values)— run a rule set against a single value.
Per-method summaries
Section titled “Per-method summaries”Each method below links to the dedicated page in the project repository for the full signature, parameters, return shape, behaviour tables, and runnable examples.
Lifecycle
Section titled “Lifecycle”form(target, options?)
Section titled “form(target, options?)”Creates a new controller bound to a form. This is the main entry point of @samline/forms.
function form( target: FormTarget, options?: FormControllerOptions): FormControllertarget— string id,HTMLFormElement, ref-like{ current }object, ornull/undefined.options— controller configuration. See Configuration.
On creation the controller wires input, change, and submit listeners at the form level, starts a MutationObserver on the form subtree, optionally enables autoSubmit, and runs an initial validation pass when autoValidate is enabled.
element
Section titled “element”Read-only getter for the bound HTMLFormElement, or null if the binding target was unresolved at construction time. f is an alias kept short for fluent setup.
readonly element: HTMLFormElement | nullreadonly f: HTMLFormElement | nullreset()
Section titled “reset()”Restores the form to its initial state: native field values reset, manual and validation errors cleared, visual attributes stripped, subscribers notified.
destroy()
Section titled “destroy()”Tears the controller down. Removes all DOM listeners, disconnects the MutationObserver, clears caches, drops subscribers and submit handlers, and resets internal state. Idempotent — calling it more than once is safe.
Submission
Section titled “Submission”onSubmit(callback, preventDefault?)
Section titled “onSubmit(callback, preventDefault?)”Registers a handler that runs when the form is submitted and validation passes. Multiple handlers can be registered; each runs in registration order.
onSubmit( callback: FormSubmitHandler, preventDefault?: boolean // default: true): FormControllerThe submit pipeline: manual errors cleared (if clearErrorsOnSubmit), validation runs, submitCount increments, handlers invoked in order. Invalid submissions are always intercepted.
autoSubmit(options?)
Section titled “autoSubmit(options?)”Enables native auto-submit. Every change to a tracked field triggers form.requestSubmit(). Pass { debounce: ms } to delay.
autoSubmit(options?: boolean | AutoSubmitOptions): FormControllerdisableAutoSubmit()
Section titled “disableAutoSubmit()”Turns auto-submit off and cancels any pending debounce timer. Equivalent to autoSubmit(false).
Field observation
Section titled “Field observation”watch(field, callback)
Section titled “watch(field, callback)”Chainable fire-and-forget reaction to a field. The callback fires only on changes (not on registration).
observe(field, callback)
Section titled “observe(field, callback)”Like watch, but fires immediately with the current value and returns an unsubscribe function.
unwatch(field?, callback?)
Section titled “unwatch(field?, callback?)”Removes watched callbacks. Three overloads: no args (clear all), field only (clear all for that field), or field + callback (clear one specific watcher).
subscribe(listener)
Section titled “subscribe(listener)”Registers a listener that fires immediately with the current state and on every subsequent state mutation. Returns an unsubscribe function. Useful for driving a view layer from a single source of truth.
Field values
Section titled “Field values”setValue(name, value)
Section titled “setValue(name, value)”Writes a value into a field and dispatches the correct DOM event so watchers, validators, and visual state run as if a user typed. Returns the controller unchanged when the field does not exist.
getValue(name)
Section titled “getValue(name)”Returns the normalized value of a field: string, string[], File[], or undefined.
getField(name)
Section titled “getField(name)”Returns the underlying DOM field(s) for a given name: a single FormFieldElement, an array (for repeated names like radio/checkbox groups), or null.
prefill(fieldName?)
Section titled “prefill(fieldName?)”Populates the form (or a single field) from the current URL query string. Delegates to setValue, so each prefilled field triggers the normal event pipeline.
format(config)
Section titled “format(config)”Apply an @samline/formatter pipeline to one or more fields inside the bound form. Creates and owns a hidden <input name="<field>Raw"> mirror so FormData/serialize() automatically exposes the raw value.
formatAll(config)
Section titled “formatAll(config)”Alias of format() for readability when field is string[].
Validation
Section titled “Validation”validate(fields?)
Section titled “validate(fields?)”Runs validation against the configured validators. Returns { isValid, errors } and marks the form as validated.
revalidate(fields?)
Section titled “revalidate(fields?)”Alias of validate kept separate for readability at call sites that want to express “re-run validation now”.
setErrors(fields)
Section titled “setErrors(fields)”Pushes manual errors into the form. Two overloads: array form (string[], default message “Invalid value.”) and map form (FormErrors, custom messages per field).
clearErrors(fields?)
Section titled “clearErrors(fields?)”Removes manual errors. Validation errors from rules are not touched. Visual attributes are re-synced for the affected fields.
State and data
Section titled “State and data”getData()
Section titled “getData()”Returns { data, formData } for the form. data is a plain object mirror (repeated names become arrays), formData is a fresh FormData instance. Empty file inputs are filtered out.
getState()
Section titled “getState()”Returns a fresh snapshot of the controller state: { values, errors, filledFields, isValid, isValidated, autoSubmit, submitCount }. Pure read — does not notify subscribers.
append(options)
Section titled “append(options)”Inserts a DOM node into the bound form. Useful for rendering banners, hints, or summary blocks that should live inside the <form> element. Returns the created HTMLElement, or null when the controller has no bound form.
Pure helpers
Section titled “Pure helpers”parseFormData(formElement)
Section titled “parseFormData(formElement)”function parseFormData(formElement: HTMLFormElement): SerializedFormResultSame serializer the controller uses internally. Returns { data, formData }. Does not require a controller.
validateValues(values, schema)
Section titled “validateValues(values, schema)”function validateValues( values: FormValues, schema: ValidationSchema): ValidationResultRuns every field in the schema against a values map. Returns { isValid, errors }.
validateFieldValue(field, value, rules, values)
Section titled “validateFieldValue(field, value, rules, values)”function validateFieldValue( field: string, value: FormFieldValue, rules: FieldValidationRules, values: FormValues): string[]Runs the rule set against a single value. Returns an array of error messages (empty when the field is valid).
Registry helpers (vanilla)
Section titled “Registry helpers (vanilla)”The vanilla entrypoint exports a browser singleton with the same shape as the IIFE bundle’s window.Forms — but as a plain ESM value with no globalThis side-effect. Use it from a bundler when you want the registry ergonomics without the IIFE.
browser
Section titled “browser”const browser: FormsApiModule-level singleton. Exposes form, newForm, destroyForm, and available. Spread it into your own globals ({ ...browser, regex }) or call its methods directly. The registry is shared across spreads, so window.Form.available and browser.available always point to the same object. See the Browser registry helpers section in the getting-started guide and FormsApi for the exact shape.
browser.newForm
Section titled “browser.newForm”Build a controller via browser.form(id, options) and store it in browser.available[id]. Accepts { id, options }. Logs Form ID is required to console.error and returns undefined if id is missing. Returns the same FormController stored under available[id].
const contact = browser.newForm({ id: 'contact-form', options: { validators: { email: { required: true } } }})browser.destroyForm
Section titled “browser.destroyForm”Look up browser.available[id], call destroy(), and delete the entry. Logs Form ID is required if id is missing, or Form with ID <id> not found if the entry is absent.
browser.destroyForm('contact-form')browser.available
Section titled “browser.available”Read-only view of the active registry: { [id: string]: FormController }. Iterate it to inspect or invoke methods on every live controller.
for (const controller of Object.values(browser.available)) { controller.validate()}For an equivalent surface in a no-bundler setup, see the Browser global reference.