Post

Twig Cheatsheet

Twig coding overview, conditional statements extends, arrays, objects, loops

How does Twig work?

Consider the following code

1
{{ foo.bar }}
  • First check that foo is an array and bar is a valid element
  • If not, and foo is an object check that bar is a valid property
  • If not and foo is an object check that bar is a valid method
  • If not and foo is an object check that getBar is a valid method
  • If not and foo is an object check that isBar is a valid method
  • If the variable passed is a render array, if it was pre- rendered, output its #markup value, otherwise, call render() on it
  • If all checks fail, return a null value.

Say Something

print text or a region to the page

1
2
{{say_something}}
{{page.highlighted}}

Do Something - control structures

1
2
3
{% if page.footer_fifth%}
{{page.footer_fifth}}
{%endif%}

Comment Something

1
{# comment something out#}

Twig Filters

1
{{ name_of_variable|name_of_filter }}
check the page array object method for footer.fifth

Reference array

1
{{variable.1}} // this is the preferred "twig" way to get first element in array

however, if the array contains a pound sign or a dash ‘-‘ sign you need to use square bracket notation

1
{{variable[1]}}

to access an array multiple levels deep, keep using the dot syntax. use square brackets if the key contains a special character. (notice the dot is used after rather then before)

Twig arrays and objects

1
2
{{variable.key.another}}
{{variable.0['#hash'].key}}

{{ variable[‘#key’]}}

1
{{page.footer_fifth}}

Booleans

Output bootstrap class

Here we output a css class based on the value of the boolean field

1
2
3
4
5
6
7
8
9
10
11
12
13
{% set mybool = content.field_name.0['#markup']  %}
{% if mybool == 'On' %}
 {% set mybool = 'my_true_val' %}
 {% else %}
 {% set mybool = 'my_false_val' %}
{% endif %}
{%
  set classes = [
    'otherclass',
    'otherclass-1',
    mybool
  ]
%}

Get value from paragraph Boolean Field

Execute from paragraph template (Paragraphs is a Drupal Module)

1
{% set stack = paragraph.field_boolean.value  %}

reverse direction

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{% set image_right = content.field_image_on_right.0['#markup'] %}
{% set direction = 'd-flex justify-content-between' %}
{% if image_right == "On" %}
  {% set direction = 'd-flex justify-content-between flex-row-reverse' %}
{% endif %}


<div class="{{ direction }}">
  <div class="col-auto">
    {{ content.field_slide_image }}
  </div>
  <div class="col-6">
    <h3 class="title">
      {{ content.field_slide_title }}
    </h3>
    {{ content.field_slide_text }}
    {{ content.field_slide_link }}
  </div>
</div>

Loops

Iterate over key value pairs

1
2
3
4
5
 <ul class='blog-post__tags field__items'>
    {% for delta, value in items %}
      <li>{{delta}}: {{ value.content }}</li>
    {% endfor %}
  </ul>

Template inheritance

  • The extends keyword lets you “dress” a template in another template’s markup.
  • The block keyword defines the customizable area where another template’s code will be dropped in.
  • All the block tag does is to tell the template engine that a child template may override those portions of the template.
  • When a template uses extends, all markup is surrounded by block tags to define the custom markup.

Add to initial template file one that you want to use as the ‘master’.

1
{% block tabcontent %} {% endblock %}

Now you can use the code from your master template in another template file

1
{% extends 'template-name.twig' %}

Inspect variables in a Drupal theme

Best way to see what variables are available os to just use dump() with no params

1
2
3
4
{{ dump() }}

{{ dump(_context|keys) }}
dump(variable_key_name)

Missing desired Keys

If you are not getting all the expected keys and you are missing some vital keys for what you need to do. Then there’s probably some configuration issue with your display mode in your manage display settings. Ensure your display mode is configured correctly and all the desired fields are set to enabled in the content region.

More info

https://drupalize.me/tutorial/arrays-and-objects-twig?p=2512

Twig Filters

just get the value from a field

1
2
    {{ content.field_description|field_value }}

Remove spaces from text

1
{{ "it would be great to combine these words" | replace({' ': ''}) }}

Remove spaces and make it lowercase

This is good for dynamically creating variable names

1
{% set my_id = some_other_var | replace({' ': ''}) | lower %}

Remove some dots from a string

1
{{ myString|replace({'.': ''}) }}

Batch

Use the batch filter when you need to turn a single list of 6 items into a two column list of 6 items (3 per column)

1
2
3
4
5
6
7
8
9
        {% for column in tab_links|batch(3, 'No item') %}
          <div class="col-12 col-sm-5">
            {% for item in column %}
                <div class="link-item">{{ item }}</div>
            {% endfor %}
          </div>
        {% endfor %}

Include, Embed, Extends

Twig Include

  • Returns the rendered content You can pass in simple key value pairs to use within your include.
1
2
3
4
5
6
{%
include '@theme_name/component/component.twig' with
   {
     key: value,
   } only
%}

Twig Embed

  • Same as includes yet they allow for the use of twig blocks
  • Blocks are used for inheritance and act as a placeholder and inheritance at the same time.
  • Twig blocks are not the same as drupal blocks
1
2
3
4
5
6
7
8
9
{%
embed '@theme_name/component/component.twig' with
   {
     key: value,
   } only
%}
{% block content %}
<p> Content can go here. </p>
{% endblock %}

Twig Extends

  • allows you to include the content of another component and replace it with blocks
1
2
3
4
5
{%
extends '@theme_name/component/component.twig' with
   {% block content %}
      <p> Some child content goes here. </p>
   {% endblock %}

Twig Debug in Drupal

Use twig debug to see what templates are actively being used by the page you are viewing. This helps front and developers apply CSS classes and HTML markup to required template files.

Twig debug also outputs many suggestions for templates that you could use in regards overriding the default templates.

alt text

Enable twig debug

In Drupal 10 switching on twig development mode is a lot easier as it’s built in to the core admin area.

Just go to /admin/config/development/settings And enable twig debug mode.

Twig for Drupal

Being new to drupal performing the simple conditional statement requires a bit of digging. My favorite php tool when dealing with something new is to grab an object and dump. I want to see whats in these things. Twig templating in drupal is made easier for all theme developers with the powerful {{dump(_context|keys)}}

See what variables are available to us

This will output a range of variables available to the template.

1
   {{ dump(_context|keys) }}

Now that we know what keys we can work with. Choose a variable from the output list to explore further

1
2
3
<pre>
   {{ dump(path) }}
</pre>

Check if user is on the Homepage

I want to hide the title if the user is on the homepage

1
2
3
   {% if path is not same as '/node/2' %}
      {{ title }}
   {% endif %}

Conditional Loading of Bootstrap Attributes

Condtional logic based on what node is being viewed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{% if path is same as '/node/37' %}
{% set classes = ['tab-pane', 'fade', 'show', 'active'] %}
{% set content_id = 'trades' %}
{% set content_role = 'tabpanel' %}
{% set content_aria_label = 'trades' %}
{% endif %}

<article {{attributes.setAttribute('id', content_id).setAttribute('role', content_role).setAttribute('aria-labelledby', content_aria_label)}} {{ attributes.addClass(classes) }}>
  {% block content %}
    <div{{ content_attributes }}>
      {{ content }}
    </div>
  {% endblock %}
</article>

if field is empty don’t render it

Avoid rendering the content if the field is empty

  • only render if the field contains content
1
2
3
4
5
6
    {% if content.title | render %}
    <h4>
      {{ content.title }}
    </h4>
    {% endif %}

check the loop index is 1

if so selected_btn will be set to ‘true’ other wise false

1
{% set selected_btn = loop.index == 1 ? 'true' : 'false' %}
This post is licensed under CC BY 4.0 by the author.