8

I have a project on D8 where I don't use any custom themes, I use default seven theme for everything because there is no need of any visual theming.

So My question: Is it possible to override theme template using module? without implementing theme at all?

I have a case where I want to add custom third party generated value in node's template.

This is what I have done:

Implemented custom template:

function MY_MODULE_theme($existing, $type, $theme, $path) {
  return array(
    'video_teaser' => [
      'template' => 'video_teaser',
      'variables' => NULL,
    ]
  );
}

Implemented hook_theme_suggestions_alter:

function MY_MODULE_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
  if(in_array('node__teaser', $suggestions)){
    $suggestions[] = 'video_teaser';
  }
} 

And this, works, instead of default template, my video_teser template is used.

BUT: I have a problem passing default node variables to my custom template, they aren't passed automatically and I couldn't find the way to do this using current approach.

1

2 Answers 2

17

You can do this in hook_theme() with the base hook 'node':

function MY_MODULE_theme($existing, $type, $theme, $path) {
  return [
    'node__video_teaser' => [
      'template' => 'node--video-teaser',
      'base hook' => 'node',
    ],
  ];
}

You don't need to define the base hook. Drupal can discover this automatically. What's important is that you use the double underscore, because this works exactly like the theme suggestions. After Drupal found the base hook it will clone the preprocess functions of this hook and will provide the variables for the node.

4
  • 1
    Thanks a lot, it worked but with little change, I had to add node__video_teaser to $suggestions using hook_theme_suggestions_alter. Another way I found was that you can add 'preprocess functions' => [ 'template_preprocess_node', ] to template definition as described on the link @Ivan commented.
    – otarza
    May 10, 2016 at 13:18
  • 2
    Are you sure about not defining the base hook? I had an issue where none of the rest of the page was getting loaded (none of the variables) until I added it. Feb 9, 2017 at 18:10
  • @4k4 - Thank you for the tip on the double underscore. This needs more visibility as it's quite simple to override a template from a module when you know the proper naming conventions within hook_theme.
    – rtd1123
    Aug 30, 2018 at 12:17
  • I found that you don't need to define the template however you do need to define the base hook. You do still need the theme suggestions alter from the question.
    – AdamS
    Aug 28, 2020 at 14:32
1

Yes, but for some cases it is not clear, I find out that for every cases you can do something like that. You need to do something like that in your custom_module_preprocess

/**
 * Implements hook_preprocess().
 */
function MY_MODULE_preprocess(&$variables, $hook, &$info) {
  $route_name = \Drupal::routeMatch()->getRouteName();
  if ($route_name == 'custom_route_name') {
    $module_path = drupal_get_path('module', 'MY_MODULE');
    if ($hook == 'html' && $variables['theme_hook_original'] == 'html') {
      $info['theme path'] = $module_path;
      $info['path'] = $module_path . '/templates';
    }
    if ($hook == 'page' && $variables['theme_hook_original'] == 'page') {
      $info['theme path'] = $module_path;
      $info['path'] = $module_path . '/templates';
    }
  }
}

It tells drupal to suggest html.html.twig and page.html.twig templates for exact route from your custom module's /templates directory.

Additionally MY_MODULE_theme_registry_alter(&$theme_registry) will work only once, only after clear caches and will not be dynamic, so you shouldn't use it!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.