Drupal 8 Theming - Define custom template file for a form

By Arun AK, 21 May, 2017

It has been three years since Drupal 8 is released. Even Drupal community has providing seamless support through forum and other resources(eg: IRC) still people are struggling during D8 development. So I'm sharing my D8 development experience here.

Majority will agree that most difficult part in Drupal development is theming. As Drupal is rendering html with its own containers and attributes achieving the exact design provided by UI developers in Drupal feels like a challenge to the developers.

Here we are going to see how can we define a custom template for a Drupal 8 webform.

Hope you are familiar with webform module. Name of form which I am going to explain in this example is ‘custom_user_register’.

First of all we have created a webform which having following fields:

  • First Name (first_name)
  • Last Name (last_name)
  • Address (address)
  • Age (age)
  • Gender (gender)

As we are going define custom template for our form we need to alter the ‘theme’ attribute of the form. Then using our custom theme function we will define our template for the form.

Here we are altering #theme attribute of our form using hook_form_alter():

function mymodulename_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if($form_id == ‘custom_user_register’) {
    $form['#theme'] = ‘custom_user_register’;
  }
}

Next we need to register our new theme function using hook_theme():

/**
 * Implements hook_theme().
 */

function mymodulename_theme($existing, $type, $theme, $path) {
  $info = [
    ‘custom_user_register’ => [
      'render element' => 'form',
      'path' => drupal_get_path('module', 'mymodulename'),
    ],
  ];
  return $info;
}

Next step, we need to create our template file inside our modules folder. Crete template ‘custom-user-register.html.twig’. Now you can render each field in your template separately like below:

{{ form.elements.first_name }}
{{ form.elements.last_name }}
{{ form.elements.address }}
{{ form.elements.age }}
{{ form.elements.gender }}
{{ form.form_build_id }} {# required #}
{{ form.form_token }}{# required #}
{{ form.form_id }} {# required #}
{{ form.actions }} {# will render the action buttons in the form #}

Hope this will help someone during Drupal 8 development and this method is useful when you need to add certain wrappers around the fields in the forms.

James (not verified)

6 years 8 months ago