Getting Granular with Drupal 8 Forms

A 1 minute read written by Clint June 15, 2017

An illustration a webform under a magnifying glass

One of the biggest pain points as a front-end dev working with Drupal is the lack of granularity when dealing with the theming of forms. While Drupal does implement default template suggestions for the form element wrapper and the individual form elements, it doesn't go beyond that in terms of template suggestions to uniquely markup and style multiple forms.

We need more options

By default every Drupal field inherits input.twig.html from the Stable core theme and also has a input--submit.html.twig or input--textfield.html.twig template suggestion depending on the field type. This creates a problem by having every form field marked up the same sitewide. This may work in certain scenarios but in cases where you would prefer the default submit button to be replaced with a magnifying glass icon or whatever else the design dictates, the default template suggestions are insufficient. You are forced to either get hacky with css or worse yet, just settle on the lack of flexibility that Drupal provides you.

Give me more options

Luckily there are options to get the results you desire while keeping the markup clean and concise. Kevin Quillen documented a technique on his blog that implements a form alter hook to create a data attribute on form elements. This data attribute is then used in a theme suggestions input alter hook to create a new template suggestion. It is quite brilliant in terms of flexibility but requires the developer to manually code the form id(s) of the form(s) that required the customization. I felt that with a few modifications the limitations could be removed and the template suggestions could then be implemented across all forms, sitewide.

How to do it

By using the following as the form alter hook, the form id becomes the data attribute on the input fields and submit button.

function HOOK_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $form['actions']['submit']['#attributes']['data-twig-suggestion'] = $form['#id'];
  $form['keys']['#attributes']['data-twig-suggestion'] = $form['#id'];
}

You can then in turn use the following theme suggestions input alter to create the completely custom and flexible template suggestion.

function HOOK_theme_suggestions_input_alter(&$suggestions, array $variables) {
  $element = $variables['element'];
  if (isset($element['#attributes']['data-twig-suggestion'])) {
    $suggestions[] = 'input__' . $element['#type'] . '__' . $element['#attributes']['data-twig-suggestion'];
  }
}

Tada! We have more options

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'input__submit' -->
<!-- FILE NAME SUGGESTIONS:
   x input--submit--user-login-form.html.twig
   * input--submit.html.twig
   * input.html.twig
-->

You now have the ability to completely customize your new input--templatesuggestion.html.twig file as your heart desires. Go to town!!