Using new HTML5 elements

With the release of Drupal 8, Drupal has finally entered into the realm of HTML5. The Form API now allows utilization of HTML5 input elements out of the box. These include the following element types:

  • tel
  • email
  • number
  • date
  • url
  • search
  • range

This allows your forms in Drupal to leverage native device input methods along with native validation support.

Getting ready

This recipe will walk you through adding elements to a Drupal form. You will need to have a custom form implemented through a module, such as the one created in the Creating a form section.

How to do it…

  1. In order to use the telephone input, you need to add a new form element definition of the tel type to your buildForm method:
      $form['phone'] = array(
        '#type' => 'tel',
        '#title' => t('Phone'),
      );
  2. In order to use the e-mail input, you need to add a new form element definition of the email type to your buildForm method. It will validate the format of e-mail addresses in the Form API:
    $form['email'] = array(
        '#type' => 'email',
        '#title' => t('Email'),
      );
  3. In order to use the number input, you need to add a new form element definition of the number type to your buildForm method. It will validate the range and format of the number:
      $form['integer'] = array(
        '#type' => 'number',
        '#title' => t('Some integer'),
        // The increment or decrement amount
        '#step' => 1,
        // Miminum allowed value
        '#min' => 0,
        // Maxmimum allowed value
        '#max' => 100,
      );
  4. In order to use the date input, you need to add a new form element definition of the date type to your buildForm method. You can also pass the #date_date_format option to alter the format used by the input:
      $form['date'] = array(
        '#type' => 'date',
        '#title' => t('Date'),
        '#date_date_format' => 'Y-m-d',
      );
  5. In order to use the URL input, you need to add a new form element definition of the url type to your buildForm method. The element has a validator to check the format of the URL:
      $form['website'] = array(
        '#type' => 'url',
        '#title' => t('Website'),
      );
  6. In order to use the search input, you need to add a new form element definition of the search type to your buildForm method. You can specify a route name that the search field will query for autocomplete options:
      $form['search'] = array(
        '#type' => 'search',
        '#title' => t('Search'),
        '#autocomplete_route_name' => FALSE,
      );
  7. In order to use the range input, you need to add a new form element definition of the range type to your buildForm method. It is an extension of the number element and accepts a min, max, and step property to control the values of the range input:
      $form['range'] = array(
        '#type' => 'range',
        '#title' => t('Range'),
        '#min' => 0,
        '#max' => 100,
        '#step' => 1,
      );

How it works…

Each type references an extended class of DrupalCoreRenderElementFormElement. It provides the element's definition and additional functions. Each element defines a prerender method in the class that defines the input type attribute along with other additional attributes.

Each input defines its theme as input__TYPE, allowing you to copy the input.html.twig base to input.TYPE.html.twig for templating. The template then parses the attributes and renders the HTML.

Some elements, such as e-mails, provide validators for the element itself. The e-mail element defines the validateEmail method. Here is an example of the code from DrupalCoreRenderElementEmail::valdateEmail:

  /**
   * Form element validation handler for #type 'email'.
   *
   * Note that #maxlength and #required is validated by _form_validate() already.
   */
  public static function validateEmail(&$element, FormStateInterface $form_state, &$complete_form) {
    $value = trim($element['#value']);
    $form_state->setValueForElement($element, $value);

    if ($value !== '' && !Drupal::service('email.validator')->isValid($value)) {
      $form_state->setError($element, t('The email address %mail is not valid.', array('%mail' => $value)));
    }
  }

This code will be executed on form submission and validate the provider's e-mail. It does this by taking the current value and trimming any whitespaces and using the form state object to update the value. The email.validator service is invoked to validate the e-mail. If this method returns false, the form state is invoked to mark the element as the one that has an error. If the element has an error, the form builder will prevent form submission, returning the user to the form to fix the value.

There's more…

Elements are provided through Drupal's plugin system and are explored in detail in the next section.

Specific element properties

Elements can have their own unique properties along with individual validation methods. At the time of writing, the Drupal 8 Form Reference table is incomplete and does not highlight these new elements nor their properties. However, the classes can be examined and the definition method can be read to learn about the properties of each element. These classes are under the DrupalCoreRenderElement namespace located in /core/lib/Drupal/Core/ Render/Element:

Specific element properties

Creating new elements

Each element used in the Form API extends the DrupalCoreRenderElementFormElement class, which is a plugin. Modules can provide new element types by adding classes to their Plugins/Element namespace. Refer to Chapter 7, Plug and Play with Plugins for more information on how to implement a plugin.

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset