How does Twig work?
Consider the following code
- 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%}
|
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
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’]}}
Get value from paragraph Boolean Field
Execute from paragraph template (Paragraphs is a Drupal Module)
1
| {% set stack = paragraph.field_boolean.value %}
|
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.
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>
|
Get value from boolean and 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
]
%}
|
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' %}
|