Validation
Validate form submissions using the AJAX framework.
Validating forms checks the user input against a set of predefined rules. When using the AJAX framework form validation occurs without any special configuration, where the invalid field will be focused and an error message is displayed (usually as an alert window).
# Flash Validation
For basic validation, including the data-request-flash
attribute on the HTML form tag provides a clean and simple interface for displaying validation messages and is usually good enough for most implementations.
<form data-request="onSubmit" data-request-flash>
<div>
<label>Name</label>
<input name="name" />
</div>
<button data-attach-loading>
Submit
</button>
</form>
Inside your AJAX handler, you may throw a validation exception using the ValidationException
class to make a field invalid. The supplied array (first argument) should use field names for the keys and the error messages for the values.
function onSubmit()
{
if (!post('name')) {
throw new ValidationException(['name' => 'You must give a name!']);
}
}
When the AJAX framework encounters the ValidationException
, it will automatically focus the first invalid field and display error messages, if configured.
# Inline Validation
For a more comprehensive validation experience, inline validation can be enabled by including the data-request-validate
attribute on the HTML form tag. The following is a minimal example of form validation using this approach with the error message displayed within the form.
<form data-request="onSubmit" data-request-validate>
<div class="alert alert-danger" data-validate-error>
<!-- Validation Message -->
</div>
<div>
<label>Name</label>
<input name="name" />
</div>
<button data-attach-loading>
Submit
</button>
</form>
# Validating a Single Field
In some cases you may want to validate a single field when the value changes. By including the data-track-input
attribute alongside the data-request
attribute, the AJAX framework will submit a request when a user types something in to the field.
<form data-request-validate>
<div>
<label>Username</label>
<input name="username" data-request="onCheckUsername" data-track-input />
</div>
</form>
A dedicated AJAX handler can be used to validate the field. If no exception is thrown, it can be considered valid.
function onCheckUsername()
{
if (true) {
throw new ValidationException(['username' => 'Username is taken!']);
}
}
# Using the Validation Service
View the Validation article to learn about the different rules you can use here.
For more complex validation, you may use the Request
facade to apply rules to the user input in bulk. The validate
method performs validation using the specified rules (first argument), and returns the attributes and values that were validated as an array. It also throws a ValidationException
if the validation fails.
function onSubmit()
{
$data = Request::validate([
'name' => 'required',
'email' => 'required|email',
]);
// The code will not reach here if validation fails
Flash::success('Jobs done!');
}
# Custom Error Messages & Attributes
To change the default validation messages, you may pass custom messages to the validate
method. The keys in the messages array (third argument) follow the attribute.rule
format.
$messages = [
'email.required' => 'Please type something for the email...',
'email.email' => 'That email is not an email...!'
];
$data = Request::validate($rules, $messages);
If you want to keep the default validation messages, and only change the :attribute
name used, pass custom attributes as an array (fourth argument).
$attributeNames = [
'email' => 'e-mail address'
];
$data = Request::validate($rules, [], $attributeNames);
# Displaying Error Messages
Inside the form, you may display the first error message by using the data-validate-error
attribute on a container element. The content inside the container will be set to the error message and the element will be made visible.
<div data-validate-error></div>
To display multiple error messages, include an element with the data-message
attribute. In this example the paragraph tag will be duplicated and set with content for each message that exists.
<div class="alert alert-danger" data-validate-error>
<p data-message></p>
</div>
# Displaying Errors with Fields
If you prefer to show validation messages for individual fields, define an element that uses the data-validate-for
attribute, passing the field name as the value.
<!-- Input field -->
<input name="phone" />
<!-- Validation message for the field -->
<div data-validate-for="phone"></div>
If the element is left empty, it will be populated with the validation text from the server. Otherwise you can specify any text you like and it will be displayed instead.
<div data-validate-for="phone">
Oops.. phone number is invalid!
</div>
# Displaying Errors with Flash Messages
When using the data-request-validate
attribute in combination with the data-request-flash
attribute, the validation errors take priority and suppress the flash message. To display both at the same time, set the attribute to a wildcard (*
) to display all flash message types, including validation.
<form
data-request-validate
data-request-flash="*">
# Working with JavaScript
To implement custom functionality for the error messages, hook into the ajax:invalid-field
event to display the field and ajax:promise
to reset the form on a new submission. The JavaScript events used are found in the AJAX JavaScript API.
addEventListener('ajax:invalid-field', function(event) {
const { element, fieldName, errorMsg, isFirst } = event.detail;
element.classList.add('has-error');
});
addEventListener('ajax:promise', function(event) {
event.target.closest('form').querySelectorAll('.has-error').forEach(function(el) {
el.classList.remove('has-error');
});
});
# Complete Usage Example
Below is a complete example of form validation. It calls the onSubmitForm
event handler that triggers a loading submit button, performs validation on the form fields, then displays a successful flash message.
The data-request-flash
attribute is used to enable flash messages for successful messages and display the validation message. The data-attach-loading
attribute is used to display a loading indicator and prevent double submissions from misclicks.
<form
data-request="onSubmitForm"
data-request-validate
data-request-flash>
<div>
<label>Username</label>
<input name="username"
data-request="onCheckUsername"
data-track-input
data-attach-loading />
<span data-validate-for="username"></span>
</div>
<div>
<label>Email</label>
<input name="email" />
<span data-validate-for="email"></span>
</div>
<button data-attach-loading>
Submit
</button>
<div class="alert alert-danger" data-validate-error>
<p data-message></p>
</div>
</form>
The onSubmitForm
AJAX event handler looks at the POST data sent by the client and applies some rules to the validator. If the validation fails, a ValidationException
is thrown, otherwise a Flash::success
message is returned.
The onCheckUsername
checks to see if a username is available, currently hard-coded to prevent names admin and jeff from being entered. It is checked twice, when the user types something in and when the user submits the form.
function onSubmitForm()
{
$data = Request::validate([
'username' => 'required',
'email' => 'required|email',
]);
$this->onCheckUsername();
Flash::success('Jobs done!');
}
function onCheckUsername()
{
$username = strtolower(trim(post('username')));
$isTaken = in_array($username, ['admin', 'jeff']);
if ($isTaken) {
throw new ValidationException(['username' => 'Username is taken!']);
}
}