Skip to content

Browser global

Use the browser build when you do not have a bundler and need to integrate the package directly into HTML, Shopify, WordPress, or any traditional template that does not run through a build step.

For every other case (modern apps, bundlers, TypeScript projects), use the main vanilla entrypoint — see Getting started.

<script src="https://unpkg.com/@samline/forms@2.7.2/dist/browser/global.global.js"></script>

The bundle is a single IIFE that registers a global object. Place the <script> tag in <head> with defer, or before the user script in <body>.

The browser build exposes window.Forms (also reachable via globalThis.Forms).

window.Forms = {
form,
newForm,
destroyForm,
available
}
  • form is the same factory exported by @samline/forms — see form().
  • newForm and destroyForm are ergonomic wrappers that keep a registry under Forms.available, keyed by the form id.

The factory returns a FormController with the same signatures, semantics, and behaviours as the main vanilla entrypoint — every per-method page in API reference applies.

<form id="contact-form">
<input name="email" type="email" />
<input name="message" />
<button type="submit">Send</button>
</form>
<script src="https://unpkg.com/@samline/forms@2.7.2/dist/browser/global.global.js"></script>
<script>
const contactForm = window.Forms.newForm({
id: 'contact-form',
options: {
validators: {
email: {
required: true,
pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/
},
message: { required: true, minLength: 10 }
}
}
})
contactForm.onSubmit(async (_element, _data, formData) => {
await fetch('/api/contact', { method: 'POST', body: formData })
contactForm.reset()
})
</script>

The controller returned by newForm is the same instance stored under Forms.available['contact-form']. Use window.Forms.destroyForm('contact-form') later to call destroy() and remove it from the registry.

Helper Purpose
Forms.newForm({ id, options }) Destroy any existing controller under the id, build a replacement via Forms.form(id, options), and store it in Forms.available[id]. Logs Form ID is required and returns early if id is missing.
Forms.destroyForm(id) Look up Forms.available[id], call destroy(), and delete the entry. Missing ids log an error; absent entries log a warning.
Forms.available Shared mutable registry: { [id: string]: FormController }. Prefer newForm() and destroyForm() to manage it.

Use Forms.form directly when you do not want the registry side-effect (for example, transient controllers in tests).

The browser bundle ships only the registry helpers plus the form factory. Every controller method is documented under API reference.

Global Purpose
Forms.form(target, options?) Bind a controller to a form (recommended). See form().
Forms.newForm({ id, options? }) Build + register a controller in Forms.available[id].
Forms.destroyForm(id) Destroy + unregister a controller by id.
Forms.available Registry of active controllers keyed by id.

The controller returned by form / newForm exposes the methods documented in API reference:

The module entrypoint @samline/forms/browser ships types, installs globalThis.Forms, and exposes default plus named registry exports. The direct IIFE subpath does not expose a typed module export.

import Forms from '@samline/forms/browser'
Forms.newForm({ id: 'contact-form' })
window.Forms.destroyForm('contact-form')

See FormsApi for the full shape.

For an ESM/CommonJS/IIFE comparison, see Entrypoints and module formats.

If you have a bundler but still want the newForm / destroyForm / available ergonomics — without the IIFE and without window.Forms auto-installed — import the browser singleton from the vanilla entrypoint:

import { browser } from '@samline/forms'
browser.newForm({ id: 'contact-form' })
browser.destroyForm('contact-form')
browser.available // { 'contact-form': FormController }

browser is a module-level singleton with a shared available registry. Spread it into your own global to compose with extra helpers like regex from @samline/formatter:

import { browser } from '@samline/forms'
import { regex } from '@samline/formatter'
window.Form = { ...browser, regex }
window.Form.newForm({ id: 'contact-form' })
window.Form.destroyForm('contact-form')

Because the registry is shared across spreads, window.Form.available and browser.available point to the same object. For independent registries, call form() directly and manage your own map — browser is designed for the one-registry-per-page case. See the Browser registry helpers section in the getting-started guide for the full pattern.

  • Pin the version. The CDN URL above uses @2.7.2. Replace it whenever you upgrade.
  • The script must be loaded before any code that uses window.Forms. Place the <script> tag in <head> with defer, or before the user script in <body>.
  • No bundler means no tree-shaking. The global browser bundle includes the controller and formatter peer. Inspect the published artifact when bundle size is a constraint.
  • CSP: if your site uses a strict Content Security Policy, allow unpkg.com in script-src (or self-host the file).