How to check if help for form element exists? - twig

Is there any way to check if form help exists directly in Twig template?
Pseudocode:
{% if formName.formField.help %}
{# ... #}
{% endif %}

You can use this:
{% if formName.formField.vars.help is not null %}
{# ... #}
{% endif %}

Another solution is just to use the filter default (if the value is not boolean though)
{% if formName.formField.vars.help|default %}
true
{% else %}
false
{% endif %}
demo

Related

How to break “for loop” in Django template

My code is:
{% for key, value in section.items %}
{% for key_t, value_t in title.items %}
{% if value_t.section_id == key|add:"0" %}
<li class="nav-item-header"><div class="text-uppercase font-size-xs line-height-xs">
{{value.title}}</div> <i class="icon-menu" title="Tables"></i></li>
{% endif %}
{% endfor %}
{% endfor %}
I want to break the for loop when if the condition is true. like as
{% for key, value in section.items %}
{% for key_t, value_t in title.items %}
{% if value_t.section_id == key|add:"0" %}
<li class="nav-item-header"><div class="text-uppercase font-size-xs line-height-xs">
{{value.title}}</div> <i class="icon-menu" title="Tables"></i></li>
{{break}}
{% endif %}
{% endfor %}
{% endfor %}
How is it possible? please help me...
There is no way to break out of a for loop in Django Template. However, you can achieve this by setting a variable and adding an if statement on the top like this.
{% set isBreak = False %}
{% for number in numbers %}
{% if 99 == number %}
{% set isBreak = true %}
{% endif %}
{% if isBreak %}
{# this is a comment. Do nothing. #}
{% else %}
<div>{{number}}</div>
{% endif %}
{% endfor %}
for some additional help check out this link
https://dev.to/anuragrana/for-loops-in-django-2jdi
or check this answer on stack overflow
How to break "for loop" in Django template

how should i put conditional statements on a node drupal 8?

I am new to drupal 8. I want something like this:
{% if node.2 %}
...............
.........
{% endif %}
what is the correct code for this? In back end I have created several nodes like node/1, node/2. I want to put a condition in node.html.twig.
how can I achieve this?
Got to twig documentation:
{% if node is not empty %}
{% for oneNode as node %}
{{ oneNode.title }}
{{ oneNode.body }}
..................
{% endfor %}
{% endif %}
Try Like this way....
{% if node.id == 2 %}
YOUR CODE..............
{% endif %}

Twig variable variable

There are some Twig arrays:
feeds, where a feed gets category_name;
events, news, announces with posts.
Therefore, I can get posts for a category that way:
{% for feed in feeds %}
{% if feed.category_name == "events" %}
{% for post in events %}
{{post.title}}
{% endfor %}
{% endif %}
{% endfor %}
Can I get the same output (as above one loop returns) with category_name string set as array name?
Here feed.category_name returns events:
{% for feed in feeds %}
{% for post in feed.category_name %} {# feed.category_name == "events" #}
{{post.title}}
{% endfor %}
{% endfor %}
I think what the question author means is – access the array using a name derived from another variable. So that extra conditions are not necessary (and most answers here do propose extra conditions).
Based on my several-minute-research, Volt alone won't let you do it. However, since you can embed PHP code in Volt templates and twig files are compiled to PHP later on anyway, you could do something like:
{% for feed in feeds %}
<?php foreach (${$feed.category_name} as $post) { ?>
{{post.title}}
<?php } ?>
{% endif %}
{% endfor %}
I have already tested this – it does work. You may want to add an extra check if the array exists, to avoid warnings:
{% for feed in feeds %}
<?php
if (!empty(${$feed.category_name})) {
foreach (${$feed.category_name} as $post) {
?>
{{post.title}}
<?php } } ?>
{% endif %}
{% endfor %}
If you don't like the idea of embedding PHP in your template – don't forget that your template is going to be compiled as PHP anyway!
The global variable _context holds all variables in the current context, so you can do this:
{% for feed in feeds %}
{% for post in _context[feed.category_name]|default(null) %}
{{ post.title }}
{% endfor %}
{% endfor %}
The |default(null) is required to prevent Twig from throwing an exception if the variable is not found.
See TwigFiddle
You want the conditional to be "added" to the loop? I think you mean this in Twig Documentation:
<ul>
{% for user in users if user.active %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
Edit
Your main issue was with the "variable variable". You can solve this with the attribute() function and combining the different feeds into one assoc array (categories?).
So perhaps something like (untested):
{% for feed in feeds %}
{% for post in attribute(categories, feed.category_name) %}
{{post.title}}
{% endfor %}
{% endfor %}
Based on your comment :
{% set new_array = news|merge(events) %}
{% for feed in feeds if attribute(feed.category_name, ['events', 'news']) %}
{% for post in new_array %}
{{post.title}}
{% endfor %}
{% endif %}
{% endfor %}

Is it possible to turn on spaceless mode only in certain situations in twig?

I want to do something like this:
{% if compress %}{% spaceless %}{% endif %}
...
{% if compress %}{% endspaceless %}{% endif %}
I'm trying to pass ['compress' => true] to the template from PHP to turn on spaceless mode. But it causes an error; template tags need to be nested properly.
Is there any technique that would let me turn spaceless on/off from PHP?
You would have to restructure your template to do something like this instead.
{% import _self as example %}
{% macro stuff(obj) %}
output stuff with {{ obj.name }}, etc...
{% endmacro %}
{% if compress %}
{% spaceless %}
{{ example.stuff(bla) }}
{% endspaceless %}
{% else %}
{{ example.stuff(bla) }}
{% endif %}
Using macros avoids you have to duplicate the content. The import statement at the top is important, so don't forget it.
page.twig:
{% block page %}
page content
{% endblock %}
index.twig:
{% extends 'page.twig' %}
{% block page %}
{% if compress %}
{% spaceless %}
{{ parent() }}
{% endspaceless %}
{% else %}
{{ parent() }}
{% endif %}
{% endblock %}

Dynamic block name in TWIG

I need to add multiple blocks in my template, every with different name.
{% for item from items %}
{% block item.name %}sometext{% endblock %}
{% endfor %}
But I get error. How can I do this ?
In
Dynamic block names are not possible with Twig. There has been a discussion about it over at GitHub.
You can load blocks dynamically using the block function.
{% for item in items %}
{{ block( item.name )|raw }}
{% endfor %}
Twig documentation for the block function
If I understood the question correctly, you can do this (use parent context):
parent.html.twig
{% for item from items %}
{% set currentLoopItemName = item.name %}
{% block item_loop %}sometext{% endblock %}
{% endfor %}
override.html.twig
{% extends "base.html" %}
{% block item_loop %}
{% if item.name == 'custom' %}
// do something
{% else %}
{{ parent() }}
{% endif %}
{% endblock %}
I was attempting to do the same thing and found a solution using the template_from_string function.
_items.html.twig
{% for item in items %}
{{ '{% block ' ~ item.name ~ ' %}'}}
sometext
{{ '{% endblock %}' }}
{% endfor %}
enter code here
page.html.twig
{% embed template_from_string(include('_items.html.twig')) %}
{% block someItemName %} someDifferentText {% endblock %}
{% endembed %}
What's happening is the block tags are initially being created as text. Then we use the include function to get the rendered content of _items, as a string. Finally, we convert that string to a working template (which we can embed or extend).
This works because the template_from_string function will create and compile a template at runtime, where as normally twig is compiled before hand and unchanged at runtime.

Resources