10

In my template preprocess function I have a variable:

$test = "<p>this is a paragraph</p>";

and I pass it to my template:

$variables['test'] = $test;

and output it in twig:

{{test}}

but instead of getting a formatted paragraph, I'm getting the original output in plain text:

<p>this is a paragraph</p>

How do I get Drupal to render this as normal HTML?

0

2 Answers 2

18

Because twig auto-escapes unsafe content and your content isn't marked as safe.

You can explicitly tell it that it is with $test = Markup::create($test); but you should be very careful with that. If it contains any sort of user input, you might open yourself for XSS issues.

Better approaches are using a render array like ['#markup' => 'your text'] which by default will allow a certain amount of html tags but not all of them. You can also use an inline template as documented here: https://www.drupal.org/node/2311123.

Twig natively understands render arrays, so it doesn't matter for your template if you provide a render array or a string.

5
  • 2
    I found that by using the raw filter, I get the output I need, so: {{test|raw }} gives 'this is a paragraph' without the markup.
    – RominRonin
    Commented Jan 22, 2016 at 16:14
  • 1
    ok, so raw is unsafe and I don't understand how I should use the example documentation you provided
    – RominRonin
    Commented Jan 22, 2016 at 16:19
  • 1
    Ok, with the help of some #drupal IRC idlers I found this: drupal.org/node/2296163 which contains a few options for outputting markup in twig.
    – RominRonin
    Commented Jan 22, 2016 at 17:20
  • 1
    In my example, I retrieved $test from a db query, and the field data was stored with markup (basic html ckeditor field), so the #markup method was the most relevant for this use case.
    – RominRonin
    Commented Jan 22, 2016 at 17:21
  • @RominRonin, just seen this comment. If this is data stored in a formatted text field this is a completely different question. Then #markup is unsafe. You have to render it with processed_text. See drupal.stackexchange.com/questions/223967/…
    – 4uk4
    Commented Apr 6, 2022 at 7:25
15

These are two possibilities to wrap $test in a paragraph and pass it to the twig template:

$variables['test'] = [
  '#markup' => $test,
  '#prefix' => '<p>',
  '#suffix' => '</p>',
];

$variables['test'] = [
  '#type' => 'inline_template',
  '#template' => '<p>{{ text }}</p>',
  '#context' => [
    'text' => $test,
  ],
];
1
  • I was trying to create a render array in Twig to pass that to a sub-template via include. The Markup render array doesn't work, but the inline_template worked. Yea, seems like I need to pass the #allowed_tags too.
    – Harish ST
    Commented Jun 20, 2023 at 8:49

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.