Drupal 8 - Inline messages validation in forms



Feb 16th 2017 in code

First of all, let’s review some vocabulary:

When we talk about forms, you may have heard some different terms, such as: Submit validation, Live validation, Live inline validation, Flash messages validation or Inline message validation... All of them are very similar, so it might be easy to get lost.

To understand all of it, let’s go back to the basics :

The creative process of a form can be divided in two phases:

  • The processing part, which includes the send method and the validity rules,
  • The visual part, which will give feedback instructions on validations.

Phase #1 — Choose a validation method

Validation methods are techniques and technologies used in order to check the validity of an input.

They are 2 kinds:

1. Standard/Submit validations are a classic server-side validation serving error pages and including the states of inputs. This kind of validation needs the form to be submitted before giving feedback to the user. Standard inline validation

2. Live validations: The check is made asynchronously, using Javascript and Ajax, which bring the user direct feedback when he/she types or leaves given fields. Live inline validation

Phase #2 — Choose a look

This is the UI & UX of your validation messages. The way they will look like.

This is where your strategy takes place to give clear visual and instruction feedback on form validations.

They are two kinds:

Flash/Growl messages: They are often shown at the top of the form and contain all your validation messages.

Inline messages: are a preferable way to display validation below or near the field.

Now that we have defined these two phases, you can merge them and create a form.

This article explains the more technical/code approach of Standard/Submit validations with Inline messages on Drupal 8 forms.

If you’re interested in reading more about forms methodology or design techniques, check out this collection of articles :

Forms Need Validation
Designing inline validation and error handling

Form validation best practices
A case study of how to get it right

Inline validation in forms 
 Designing the experience

Web Form Validation
Best Practices and Tutorials

Coding Standard inline validations using Inline Messages validation in Drupal 8

This part is based on the assumption that you are fully comfortable with Object Oriented Programming (OOP) and the use of the Form API with Drupal 8.

Coding like a robot

Let's start the fun part: coding !

Create your form

Begin by creating a form using the Drupal 8 Form API, this form will just display a Success Flash/Growl message when submitted.

Add some validations

Now that we have a functional form, let's add a few verifications and validations to it. The easier way is to continue and use the well known method to set an error on a field: FormState::setErrorByName.
By using the setErrorByName of FormState, Drupal 8 will add every messages to the Flash/Growl message region as shown in the picture below:

Bag Form Validation

Disable the cache

Well, let's get into the heart of this article, our final goal is to replace the standard Drupal Flash messages validation with a more elegant method - Inline messages validation.

The first thing to do is to disable the form cache.

We want to rebuild the form build every time we display it and show contextual Inline messages validation.

// Disable caching
$form['#cache']['max-age'] = 0;

Implement Inline messages validation

Before you begin, you need to add a small dependency: composer require symfony/property-access:^3.2.

For now we have a beautiful form but all our validations messages are shown into a single Flash messages validation block atop of our form. Finally, we can now code your Inline messages validation. It will look like:

Inline Form Validation

Done ! Congratulations.

Go further

Disable default Drupal validations

Sometime you will need to disable the automatic HTML5 validations. If you keep it enabled, Drupal 8 will run some of its validations before yours, such as an email validation or just on mandatory fields. This will add every message to the Flash/Growl Bag Messages System and nothing will go through your custom validations before the Drupal ones are valid.

The result is a bad user experience. They will see 2 displays of validations for the same fields (Flash - Drupal & Inline - Yours).

// Disable browser HTML5 validation
$form['#attributes']['novalidate'] = 'novalidate';

Keep the form after submit instead of the page top

This is far simpler than you may think, you just have to use the ID of your form and use it as an anchor when submitting.

// This will generate an anchor scroll to the form when submitting
$form['#action'] = '#my-contact-form';

Unique name for every fields

In fact, at the first sight it seems like you have to keep every field with a unique name to retrieve data with $form_state->getValue('subject') but in reality you can configure every field to be nested using the hierarchy of your form with the following line :

// Submitted form values should be nested.
$form['#tree'] = TRUE;

And retrieve data with :