When a form field with this attribute is changed, the form is validated on the server and is updated with validation messages.
To validate the form, Unpoly will submit the form with an additional X-Up-Validate
HTTP header.
When seeing this header, the server is expected to validate (but not save)
the form submission and render a new copy of the form with validation errors.
The programmatic variant of this is the up.validate()
function.
Let's look at a standard registration form that asks for an e-mail and password:
<form action="/users">
<label>
E-mail: <input type="text" name="email" />
</label>
<label>
Password: <input type="password" name="password" />
</label>
<button type="submit">Register</button>
</form>
When the user changes the email
field, we want to validate that
the e-mail address is valid and still available. Also we want to
change the password
field for the minimum required password length.
We can do this by giving both fields an up-validate
attribute:
<form action="/users">
<label>
E-mail: <input type="text" name="email" up-validate />
</label>
<label>
Password: <input type="password" name="password" up-validate />
</label>
<button type="submit">Register</button>
</form>
Whenever a field with up-validate
changes, the form is POSTed to
/users
with an additional X-Up-Validate
HTTP header.
When seeing this header, the server is expected to validate (but not save)
the form submission and render a new copy of the form with validation errors.
In Ruby on Rails the processing action should behave like this:
class UsersController < ApplicationController
* This action handles POST /users
def create
user_params = params[:user].permit(:email, :password)
@user = User.new(user_params)
if request.headers['X-Up-Validate']
@user.valid? # run validations, but don't save to the database
render 'form' # render form with error messages
elsif @user.save?
sign_in @user
else
render 'form', status: :bad_request
end
end
end
Note that if you're using the unpoly-rails
gem you can simply say up.validate?
instead of manually checking for request.headers['X-Up-Validate']
.
The server now renders an updated copy of the form with eventual validation errors:
<form action="/users">
<label class="has-error">
E-mail: <input type="text" name="email" value="foo@bar.com" />
Has already been taken!
</label>
<button type="submit">Register</button>
</form>
The <label>
around the e-mail field is now updated to have the has-error
class and display the validation message.
Although the server will usually respond to a validation with a complete,
fresh copy of the form, Unpoly will by default not update the entire form.
This is done in order to preserve volatile state such as the scroll position
of <textarea>
elements.
By default Unpoly looks for a <fieldset>
, <label>
or <form>
around the validating input field, or any element with an
up-fieldset
attribute.
With the Bootstrap bindings, Unpoly will also look
for a container with the form-group
class.
You can change this default behavior by setting up.form.config.validateTargets
:
// Always update the entire form containing the current field ("&")
up.form.config.validateTargets = ['form &']
You can also individually override what to update by setting the up-validate
attribute to a CSS selector:
<input type="text" name="email" up-validate=".email-errors">
<span class="email-errors"></span>
The [up-validate]
behavior is also a great way to partially update a form
when one fields depends on the value of another field.
Let's say you have a form with one <select>
to pick a department (sales, engineering, …)
and another <select>
to pick an employeee from the selected department:
<form action="/contracts">
<select name="department">...</select> <!-- options for all departments -->
<select name="employeed">...</select> <!-- options for employees of selected department -->
</form>
The list of employees needs to be updated as the appartment changes:
<form action="/contracts">
<select name="department" up-validate="[name=employee]">...</select>
<select name="employee">...</select>
</form>
In order to update the department
field in addition to the employee
field, you could say
up-validate="&, [name=employee]"
, or simply up-validate="form"
to update the entire form.
The CSS selector to update with the server response. This defaults to a fieldset or form group around the validating field.