constraint-validation-example

Expand History Expand History
Collapse History Collapse History

Integrate with Browser Constraint Validation API

Progressively enhance forms with real-time validation message reporting through the Constraint validation API.

First, render form elements with declarative validation attributes that match their ActiveModel::Validation counterparts.

When rendering a form, declare a <template> element by calling #validation_message_template with a block. Render the <template> element with the contents of an “empty” call of that block. Assign the block as a FormBuilder-local instance variable, and use it to construct elements in subsequent calls to #validation_message. By ensuring that both server-side and client-side validation messages are rendered with the same HTML, we can unify our error reporting.

invalid events

Next, declare listeners to intercept invalid events.

Unfortunately, the InvalidEvent does not bubble, so these need to be declared directly on the fields themselves.

In order to listen for dispatched InvalidEvent without relying on bubbling mechanics, the document-level addEventListener call must pass a third parameter that specifies { capture: true }. Additionally, since the listener can invoke Event.preventDefault, also specify { passive: false }.

When handling an invalid event, find an existent validation message element or create a new one from the form’s <template>. Replace the element’s innerHTML with the validation message, and ensure that the references to the corresponding element (like [aria-invalid="true"], [aria-describedby], [id], etc.) are intact.

Finally, re-validate through a call to reportValidity() when the input loses focus.

Testing

Unfortunately, the in-Browser validation messages are not synchronized with out application’s validation messages. For example, what would be a server-side blank validation message (i.e. can't be blank) is reported by the browser as Please fill out this field.

To account for that variation, this commit updates the System tests to assert the Browser generated message.