Inline Twig templates

Inline Twig template is a quick and easy way to use Twig syntax in render arrays. I usually use this render element type to add JS scripts to the <body> section of Drupal pages, but you can also use it in controller responses, custom blocks, pseudo fields, and so on.

For example, let's say that you want to add a Google Tag Manager noscript. The documentation says that you have to place the JS snippet immediately after the opening <body> tag on every page of your website. You can use hook_page_top() and inline_template to accomplish this:

function MYMODULE_page_top(&$page) {
  $page['google_tag_noscript_tag'] = [
    '#type' => 'inline_template',
    '#template' => '<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>',
  ];
}

You can also provide variables like this:

function MYMODULE_page_top(&$page) {
  $page['google_tag_noscript_tag'] = [
    '#type' => 'inline_template',
    '#template' => '<noscript><iframe src="https://www.googletagmanager.com/ns.html?id={{ container_id }}"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>',
    '#context' => [
      'container_id' => 'GTM-XXXX',
    ],
  ];
}

Please note that you can't use the markup type here because it will strip the style attribute. So, the following doesn't work properly:

function MYMODULE_page_top(&$page) {
  $page['google_tag_noscript_tag'] = [
    '#type' => 'markup',
    '#markup' => '<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
  ];
}

#markup is passed through Xss::filterAdmin(), which strips all known XSS attack vectors. You can use #allowed_tags to specify the list of allowed tags, but that won't prevent Drupal from striping attributes. In our case, the style attribute will be stripped, so the best bet is to use the inline template.

Recently I had to add a button to a field widget, and I used the Inline Twig template like this:

/**
 * {@inheritdoc}
 */
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {

...

  $element['remove'] = [
    '#type' => 'inline_template',
    '#template' => '<a href="#" id="remove-button" class="button remove-button">' . $this->t('Remove') . '</a>',
  ];

...

}

It's quite obvious that you can find many usages for this useful render element type.

About the Author

Goran Nikolovski is a web and AI developer with over 10 years of expertise in PHP, Drupal, Python, JavaScript, React, and React Native. He founded this website and enjoys sharing his knowledge.