Client-side validation
validate: true mirrors your ActiveModel validators into shipped Stimulus controllers — the no-phlex-reactive fallback.
Turning it on#
validate: true introspects the model's validators and emits data-validations--* bindings per field, plus a form-level submit coordinator. The form gets novalidate — the shipped Stimulus controllers own error display, so you never see the inconsistent native browser bubbles.
Form(model: @partner, validate: true) do |f|
f.field :title
f.field :note
f.submit :primary
endRegister the controllers once (see Installation):
import { lazyLoadControllersFrom } from "@hotwired/stimulus-loading"
lazyLoadControllersFrom("phlex_forms/controllers", application)Per-field overrides#
Form(model: @partner, validate: true) do |f|
f.field :title # every validator on :title
f.field :slug, validate: false # opt this field out
f.field :note, validate: { length: { maximum: 30 } } # explicit inline rules
endWhat's supported#
Presence, length (with a live character counter), format, numericality, inclusion, exclusion, confirmation, and acceptance.
Validators with :if, :unless, or :on are skipped — they need server context — and uniqueness can't be checked client-side. The server stays authoritative either way; this layer is UX, not enforcement.
Messages & i18n#
Validation messages ship for en, fr, and af; override any string client-side via window.PhlexForms.messages. The engine prepends the gem's locale files to I18n.load_path, so your app's files win.