Drupal 8: Defining own template files in theme

Drupal 8: Defining own template files in theme Peter Majmesku Mon, 02/12/2018 - 13:46

You need two functions in your THEME-MACHINENAME.theme file. Let's say you want to create an own template for the form-element.html.twig file at your user login page. For example purpose, I have used an example module named manager.

Implementation of hook_theme_suggestions_form_element_alter()

The following function only creates a suggestion in your HTML markup. So you see that there is a file which can be used. That's just documentation purpose.

/**
 * Implementation of hook_theme_suggestions_form_element_alter().
 */
function manager_theme_suggestions_form_element_alter(array &$suggestions, array $variables) {
  if (\
Drupal::service('path.current')->getPath() == '/user/login') {
    
$suggestions[] = $variables['theme_hook_original'] . '--user-login';
  }
}
 

Implementation of hook_preprocess_form_element()

The following function defines the filename of your template file. Do not add a the ".html.twig" file extension. Notice that there will be an error, if the file does not exist. If you want to have this file only optional, you can use PHP's file_exists() function.

/**
 * Implementation of hook_preprocess_form_element().
 */
function manager_preprocess_form_element(&$variables$hook, &$info) {
  if (\
Drupal::service('path.current')->getPath() == '/user/login') {
    
$info['template'] = 'form-element--user-login';
  }
}
 

The ThemeManager Drupal core class

If you want to learn more about the inner workings of the template file handing, then take a look at the class in the namespace Drupal\Core\Theme\ThemeManager. See API documentation at https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Theme%21…. There's the pretty long render() function, where the template load and hook-processing happens. Like around line 261:

    // Include a file if the theme function or variable preprocessor is held
    // elsewhere.
    
if (!empty($info['includes'])) {
      foreach (
$info['includes'] as $include_file) {
        include_once 
$this->root '/' $include_file;
      }
    } 

A more reusable approach

If you want to add theme suggestions and templates for specific paths, you can use the two functions bellow. The example code is triggered at the /user/login path.

/**
 * Implementation of hook_theme_suggestions_alter().
 */
function manager_theme_suggestions_alter(array &$suggestions, array $variables) {
  
$templateSuggestionsByPath = [
    
'/user/login' => 'user-login'
  
];

  
$currentPath = \Drupal::service('path.current')->getPath();

  if (isset(
$templateSuggestionsByPath[\Drupal::service('path.current')->getPath()])) {
    
$suggestions[] = str_replace('_''-'$variables['theme_hook_original']) . '--' $templateSuggestionsByPath[$currentPath];
  }
}


/**
 * Implementation of hook_preprocess().
 */
function manager_preprocess(&$variables$hook, &$info) {
  
$templateSuggestionsByPath = [
    
'/user/login' => 'user-login'
  
];

  
$currentPath = \Drupal::service('path.current')->getPath();
  
$themePath drupal_get_path('theme', \Drupal::theme()->getActiveTheme()->getName());

  if (isset(
$templateSuggestionsByPath[$currentPath])) {
    
$template str_replace('_''-'$variables['theme_hook_original']) . '--' $templateSuggestionsByPath[$currentPath];
      if (
file_exists($themePath '/templates/' $template '.html.twig')) {
        
$info['template'] = $template;
        
$info['theme path'] = 'themes';
        
$info['path'] = $themePath '/templates';
      }
  }

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
CAPTCHA This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.