Forms
Overview of implementing forms in Zermatt using Laravel Precognition for live validation.
Forms in Zermatt are using Laravel Precognition. We invite you to read the official documentation for a better understanding of the underlying code.
As stated on the Lavarel website:
Laravel Precognition allows you to anticipate the outcome of a future HTTP request. One of the primary use cases of Precognition is the ability to provide "live" validation for your frontend JavaScript application without having to duplicate your application's backend validation rules.
This is especially useful for form validation and allows great user experience by providing (optional) live validation on each input change. The user gets instant error notification when filling a field the wrong way.
Implementation
Here are the steps required when implementing a Zermatt form.
- Create a validation controller: a native Magento controller class which extends
\Maddlen\ZermattForm\FormRules\FormRulesAbstract
. - Use the
Zermatt_Form
Zermatt module in the template files. - Use the
Zermatt_Form
API to validate and submit the form.
Validation controller
Here is a commented example of a validation controller.
class Index extends \Maddlen\ZermattForm\FormRules\FormRulesAbstract
{
public function rules(): array
{
return [
// The "name" field of the form must not be empty
'name' => [
\Magento\Framework\Validator\NotEmpty::class
],
// The "email" field of the form must not be empty and an email address
'email' => [
\Magento\Framework\Validator\NotEmpty::class,
\Magento\Framework\Validator\EmailAddress::class
]
];
}
public function redirectUrl(): string
{
// Where to redirect the user once the form was submitted
return $this->url->getUrl('custom_route');
}
public function getSuccessMessage(): ?Phrase
{
// Adds this success message once the user is redirected after form submission
return __('Form is valid');
// Or avoid displaying a success message
return null;
}
public function submitForm(): bool
{
try {
// Form submission business logic
} catch (\Exception $e) {
// Handle form submission error and return false
return false;
}
return true;
}
}
Zermatt_Form module in template
Here is a commented example of a phtml template using the Zermatt_Form
module:
// Use Zermatt.Module('Zermatt_Form') on this div
<div x-data="Zermatt.Module('Zermatt_Form', {
// formData lists all fields that require validation.
// Fields names must match the ones declared in the rules() method of the validation controller.
formData: {
name: '',
email: ''
}
})" x-cloak>
// Declare a native HTML form. Use the validation controller route as "action" attribute.
<form action="<?= $block->getUrl('zermatt_examples/form') ?>">
// Embed the form fields in an AlpineJS template tag.
<template x-if="form">
// Form container
<div>
// Field container
<div>
<label for="name_field_id">Name</label>
<input
id="name_field_id"
// Required. The name of the field as declared in the rules() method of the validation controller.
name="name"
// Required. An x-model with `form.<field>` where <field> is he name of the field as declared in the rules() method of the validation controller.
x-model="form.name"
// Optional. Proceed to live validation of this field.
@change="validate('name')"
/>
// Error display
<template x-if="form.invalid('name')"> // Checking if form is invalid for a given field
<div x-text="form.errors.name" class="mage-error"></div> // Display the error returned by the validation controller.
</template>
</div>
// Field container
<div>
<label for="email_field_id">Email</label>
<input
id="email_field_id"
name="email"
x-model="form.email"
@change="validate('email')"
/>
<template x-if="form.invalid('email')">
<div x-text="form.errors.email" class="mage-error"></div>
</template>
</div>
</div>
</template>
</form>
</div>
Avoid page reload on form submission success
You may want to avoid the user being redirected when the form is successfully submitted or change the submission success behavior.
In such case, just pass the callback to the Zermatt_Form
module with its onSubmitted
property.
A payload with the form data and the server response is provided to the callback.
// Some logic to display a custom success message.
<div x-show="showSuccess" x-data="{
showSuccess: false,
init() {
Zermatt.Event.on('myform:success', (events) => {
const { payload } = events[0].detail
console.log(payload)
this.showSuccess = payload ? true : false
})
}
}">Form is valid!</div>
<div x-data="Zermatt.Module('Zermatt_Form', {
// Pass the onSubmitted property to Zermatt_Form
onSubmitted: (payload) => Zermatt.Event.dispatch('myform:success', {payload}),
formData: {
name: '',
email: ''
}
})" x-cloak>
...
</div>