2

I'm trying to override an email template of the webform module. The project is headless so we don't have a custom theme, and we'd like to stick with the Adminimal contrib theme. However, we do have a custom module named app in web/modules/app.

Here are the default template suggestions shown in the email source:

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'webform_email_html' -->
<!-- FILE NAME SUGGESTIONS:
   * webform-email-html--contact--email--email-notification.html.twig
   * webform-email-html--contact--email.html.twig
   * webform-email-html--contact.html.twig
   x webform-email-html.html.twig
-->
<!-- BEGIN OUTPUT from 'modules/contrib/webform/templates/webform-email-html.html.twig' -->

If I just create a web/modules/app/templates/webform-email-html.html.twig file (or any of the other suggestions), the template override doesn't work: the template of the webform module is used.

2 Answers 2

2

The only way I found to get template override to work is to:

  1. add a template suggestion:
    // in web/modules/app/app.module
    function app_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
      $suggestions[] = $hook . '--' . 'custom';
    }
    
  2. force the template used to render the webform_email_html--custom template suggestion:
    // in web/modules/app/app.module
    function app_theme($existing, $type, $theme, $path) {
      return [
        'webform_email_html--custom' => [
          'template' => 'webform-email-html--custom',
        ],
      ];
    }
    
  3. create the web/modules/app/templates/webform-email-html.html.twig file

I'm not marking this answer as accepted on purpose: please tell me there's a better way, this feels overly complicated! There doesn't seem to have a better way…

2
  • 2
    This is working as intented. Themes override module templates out of the box, module do not override templates. (And should not do this out of the box to avoid collisions. There is only one active theme, but potentially hunders of active modules.)
    – Hudri
    Commented Nov 22, 2022 at 12:06
  • 3
    Please tell me there's a better way ... There is not, and this is pretty common, see for example the core comment module overriding a template of the field module which then can be overridden again by a theme. But you need to append __custom instead of --custom and define the base hook instead of the template name 'base hook' => 'webform_email_html',. You need the base hook to include the preprocess handlers of the base template and you don't need the template name because this is already defined by the hook name.
    – 4uk4
    Commented Nov 22, 2022 at 12:48
1

Thanks for this! I wanted to clean up the answer a little bit. This is essentially the same with a couple changes:

  1. Instead of creating a new theme suggestion/hook for every hook already in the system, we create one only for the hook we want to create a new template for. This is a much less heavy handed approach.
  2. As 4uk4 pointed out, dashes have been replaced with underscores.
  3. As 4uk4 pointed out, we use base hook instead of template in our hook_theme() implementation.
  4. We add path in our hook_theme() implementation, allowing us to sort templates within our module. In this case we put the template in templates/webform.
// In web/modules/app/app.module

/**
 * Implements hook_theme_suggestions_alter().
 */
function app_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
  // Use switch so we can easily add another hook in the future.
  switch ($hook) {
    case 'webform_email_html':
      $suggestions[] = $hook . '__' . 'custom';
      break;
  }
}
// In web/modules/app/app.module

/**
 * Implements hook_theme().
 */
function app_theme($existing, $type, $theme, $path) {
  return [
    'webform_email_html__custom' => [
      'base hook' => 'webform_email_html',
      'path' => $path . '/templates/webform',
    ],
  ];
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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