5

What is the alternative to the |raw filter if I want to output html from a entity field in twig in Drupal 8?

According to this ticket, |raw should be avoided, but I can't figure out how to use what they recommend in that ticket (Safestring/SafeMarkup) in twig.

I have a custom content entity that has a field definition as follows:

$fields['internal_description'] = BaseFieldDefinition::create('text_long')
  ->setLabel(t('Internal description'))
  ->setSettings(array(
    'max_length' => 1500,
  ))

The field stores HTML from a CKEditor instance. Now I would like to output this as HTML in a twig template. Currently if I just call

{{  event.getExternalDescription }}

I get the escaped HTML as expected, however that is not what I want. If I do

{{  event.getExternalDescription | raw }}

I get what I want, which is unescaped, rendered HTML. However since it's not checked in any way in this case, I would like to know how to make this output safe and still allow my users to use CKEditor for entering content?

1
  • What they do in that ticket is use a preprocess hook to add Markup render elements as twig variables. That way, there is no need for the raw filter. That way, you can use the added twig variables directly in your twig template. Commented Dec 27, 2016 at 13:03

3 Answers 3

13

Normally you would configure the display of the field in UI.

You can do this in code by using the render element processed_text.

PHP

  $build = [
    '#type' => 'processed_text',
    '#text' => '<p>Hello world</p>',
    '#format' => 'full_html',
  ];

TWIG

In twig you would use instead of the extremely unsafe {{ event.getExternalDescription | raw }} this code:

  {% set build = {
    '#type':   'processed_text',
    '#text':    event.getExternalDescription,
    '#format': 'full_html',
  } %}

  {{ build }}

The safety of the text format depends on the configuration of the text filters and the content of the field. Apply the same security considerations as you would for text formats in ckeditor.

2
  • This is not automatic when you display a field using {{ node.field_myfield}}. Why?
    – gagarine
    Commented Jun 13, 2020 at 20:26
  • As said in my answer normally you would configure the field in UI and it will be printed automatically in a node template via {{ content }} or if you need to output the field separately by using {{ content.field_myfield }}.
    – 4uk4
    Commented Jun 13, 2020 at 21:03
2

This type of usage worked for me, in making a long text wysiwyg field render that was within a paragraph entity on a node:

{{ item.entity.field_innerfieldname.value|t() }}

Specifically within nodes where field_paragraph_items is the set of paragraph elements:

{% for item in content['#node'].field_paragraph_items %}

It took a while to figure this out. the twig processor |t() is not widely advertised.

See also:

1
  • I don't think you can translate field content like this, t() is for string constants and for security reasons variables are only allowed in placeholders.
    – 4uk4
    Commented Jun 19, 2018 at 10:02
-1

After @HongPong answer (sorry, I can't comment, yet) I found the following DID work for me:

{{ node.body.value|t }}

Note there're no brakets after '|t' !

Before I was using simply {{ node.body.value }} and got the HTML tags parsed onto the webpage (e.g. '<p>') while in the webpage code got escaped AKA HTML encoded (e.g. '&lt;p&gt;').

1
  • 1
    |t is for translating string constants. Using it for variables makes your website vulnerable to XSS attacks and creates a new entry in the translation table every time you render a node. The body field is stored in a formatted text field and the only way to output it is to process the text format: {{ {'#type': 'processed_text', '#text': node.body.value, '#format': node.body.format } }}
    – 4uk4
    Commented Feb 1 at 13:06

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.