I have a conditional include which looks like this:
include:
{% if CONDITION-A %}
- foo.bar
{% endif %}
{% if CONDITION-B %}
- blu.bla
{% endif %}
This works in most cases.
But it fails if CONDITION-A and CONDITION-B are false.
How to handle this?
I use this pattern now:
include:
- dummy
{% if CONDITION-A %}
- foo.bar
{% endif %}
{% if CONDITION-B %}
- blu.bla
{% endif %}
dummy.sls:
dummy-no-op:
test.nop
Not nice, but works.
Better (simpler, more obvious) answers are welcome.
Docs for test.nop
This is also ugly, but you could wrap the entire include block in an if condtion that check if either CONDITION-A or CONDITION-B is true:
{% if CONDITION-A or CONDITION-B %}
include:
{% if CONDITION-A %}
- foo.bar
{% endif %}
{% if CONDITION-B %}
- blu.bla
{% endif %}
{% endif %}
This way jinja will remove the include block if both conditions are false
Related
I have a conditional include which looks like this:
include:
{% if CONDITION-A %}
- foo.bar
{% endif %}
{% if CONDITION-B %}
- blu.bla
{% endif %}
This works in most cases.
But it fails if CONDITION-A and CONDITION-B are false.
How to handle this?
I use this pattern now:
include:
- dummy
{% if CONDITION-A %}
- foo.bar
{% endif %}
{% if CONDITION-B %}
- blu.bla
{% endif %}
dummy.sls:
dummy-no-op:
test.nop
Not nice, but works.
Better (simpler, more obvious) answers are welcome.
Docs for test.nop
This is also ugly, but you could wrap the entire include block in an if condtion that check if either CONDITION-A or CONDITION-B is true:
{% if CONDITION-A or CONDITION-B %}
include:
{% if CONDITION-A %}
- foo.bar
{% endif %}
{% if CONDITION-B %}
- blu.bla
{% endif %}
{% endif %}
This way jinja will remove the include block if both conditions are false
Since I'm using a SaaS platform I don't have much space to do things differently.
I have two for loops in Twig:
{% for option in product.options %}
{{ option.title }}
{% if option.values %}
{% for value in option.values %}
{{ value.title }}
{% endfor %}
{% endif %}
{% endfor %}
{% for variant in product.variants %}
{{ variant.stock.level }}
{% endfor %}
What I try to do is to use variant.stock.level value inside the product.options for loop to show some HTML. This value always match the corresponding index value of the other for loop. I also think that's the only way to do this.
So what I mean is.....Let's say both for loops contain 3 elements.
Option1
Option2
Option3
Variant1
Variant2
Variant3
So option1 needs to have the value from variant1.
For the end result I need to know what the value of eg Variant1 is to show some HTML like so:
{% for value in option.values %}
{% check if value from corresponding variant is greater then 0 %}
<li class="on-stock">{{ value.title }}</li>
{% else %}
<li class="out-of-stock">{{ value.title }}</li>
{% endif %}
{% endfor %}
I don't know no other way to explain this :) Any help appreciated....
You are looking for attribute.
The attribute function can be used to access a "dynamic" attribute of a variable
Since the indexes are the same, you can use loop.index0
Example for your case
{% if attribute(option.variants, loop.index0) > 0 %}
// some stuff
{% endif %}
I'm not sure if I understood you correctly but you may use key from first loop to access product.variants with the same index.
{% for key, option in product.options %}
{{ option.title }}
{% if option.values %}
{% for value in option.values %}
{{ value.title }}
{% endfor %}
{% endif %}
{{ product.variants[key].stock.level }}
{% endfor %}
I'm trying to validate the size of an array before print a value, but the if instruction doesn't work. Always pass thought the if.
This is my code:
{% set size = custodian.phoneNumbers|length %}
{% if size > 3 %}
{% block phone_number3 %}{{phoneNumbers[2].phoneNumber }}{% endblock %}
{% endif %}
size is equal to 2
I try with this code and does not work as well.
{% set size = true %}
{% if size == false %}
{{size}}
{% endif %}
Please help!!!
Thanks in advance.
I found the answers myself
The block should be outside of the if.
{% block phone_type3 %}
{% if size >= 3 %}
{{ custodian.phoneNumbers[2].phoneType.value }}:
{% else %}
:
{% endif %}
{% endblock %}
{% block phone_number3 %}
{% if size >= 3 %}
<b>{{ custodian.phoneNumbers[2].phoneNumber }}</b>
{% endif %}
{% endblock %}
Ok, bad question since semantically I think I can gather the difference by the block names themselves. My real question is how can I control which attributes appear a container and an element when widget_attributes and widget_containter_attributes are required on a given element.
Consider the following:
<div class="ui-select foo bar baz">
<select id="abc_hello_worldtype_name" name="abc_hello_worldtype[name]" class="thud grunt">
...
</select>
</div>
Main things I'm going after are having to set class names on both the div and the select. This is required for both style reasons as well as behavior-related requirements.
The main thing that is confusing me is that both the original widget_attributes and widget_container_attributes both use the attr variable passed in. Are these not intended to be used together?
I found myself doing something like the following today; just making my own blocks copied from the originals and adding to the conditionals. This all seems way too complicated. I know I'm doing it wrong.
{% block choice_widget_collapsed %}
{% spaceless %}
{% set attr = attr|merge({'class': (attr.class|default('') ~ ' ui-select')|trim}) %}
<div {{ block('ui_select_container_attributes') }}>
<select {{ block('ui_select_widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
{% if empty_value is not none %}
<option value=""{% if required %} disabled="disabled"{% if value is empty %} selected="selected"{% endif %}{% endif %}>{{ empty_value|trans({}, translation_domain) }}</option>
{% endif %}
{% if preferred_choices|length > 0 %}
{% set options = preferred_choices %}
{{ block('choice_widget_options') }}
{% if choices|length > 0 and separator is not none %}
<option disabled="disabled">{{ separator }}</option>
{% endif %}
{% endif %}
{% set options = choices %}
{{ block('choice_widget_options') }}
</select>
</div>
{% endspaceless %}
{% endblock choice_widget_collapsed %}
Notice the ui_* block references on the div and the select. Those blocks look like:
{% block ui_select_widget_attributes %}
{% spaceless %}
id="{{ id }}" name="{{ full_name }}"{% if read_only %} readonly="readonly"{% endif %}{% if disabled %} disabled="disabled"{% endif %}{% if required %} required="required"{% endif %}{% if max_length %} maxlength="{{ max_length }}"{% endif %}{% if pattern %} pattern="{{ pattern }}"{% endif %}
{% for attrname, attrvalue in attr %}{% if attrname in ['placeholder', 'title'] %}{{ attrname }}="{{ attrvalue|trans({}, translation_domain) }}" {% elseif attrname == 'class' %} class="foopa {{ attrvalue|replace({'ui-select':''}) }}" {% else %}{{ attrname }}="{{ attrvalue }}" {% endif %}
{% endfor %}
{% endspaceless %}
{% endblock ui_select_widget_attributes %}
{% block ui_select_container_attributes %}
{% spaceless %}
{% if id is not empty %}id="{{ id }}" {% endif %}
{% for attrname, attrvalue in attr %}{{ attrname }}="{{ attrvalue }}" {% endfor %}
{% endspaceless %}
{% endblock ui_select_container_attributes %}
When a form field is rendered as single form input (text input, select, checkbox...), widget_attributes is used. When it is rendered as a collection of inputs (form, multiple checkboxes, multiple inputs, ...), widget_container_attributes is used for the container surrounding the inputs (a div, mostly). So no, they are not intended to be used at the same time.
The difference between the two blocks is that widget_attributes renders form-specific attributes ("value", "name"...) while widget_container_attributes renders only generic HTML attributes.
If you want to add additional markup beyond the possibilities of the "attr" option, your best bet is to copy the corresponding block from the form theme (e.g. "choice_widget_collapsed"), paste it into your template, rename the block to match your element's ID with a leading underscore ("_") and a "widget" suffix (e.g. if your element's ID is "form_my_element", the block would be called "_form_my_element_widget") and modify the markup in your template.
{% block body %}
...
{{ form(form) }}
...
{% endblock %}
{% block _form_my_element_widget %}
... modified version of the "choice_widget_collapsed" markup ...
{% endblock %}
I'm learning Symfony2. Currently, I'm trying to render a form label in a twig template. The label includes an html tag, that is not rendered correctly in my twig file.
Here follows the piece of code where the form field is created:
$builder->add('zipcode', 'integer', array(
'label' => '<abbr title="Zone Improvement Plan">CAP</abbr> code',
));
In the twig file I render the field label as follows:
{{ form_label(form.zipcode) }}
I tried the raw, escape, e filters, but the results provided in my html page is always the string
<abbr title="Zone Improvement Plan">CAP</abbr> code
and not the corresponding HTML code!
Any suggestion?
Thanks in advance!
Later I found the solution.
The solution is to disable the autoescape within the label block provided by Symfony at path:
symfony / src / Symfony / Bridge / Twig / Resources / views / Form / form_div_layout.html.twig
So, in your twig file you have to put the following lines outside the form:
{% form_theme form _self %}
{% block generic_label %}
{% spaceless %}
{% if required %}
{% set attr = attr|merge({'class': attr.class|default('') ~ ' required'}) %}
{% endif %}
<label{% for attrname,attrvalue in attr %} {{attrname}}="{{attrvalue}}"{% endfor %}>{% autoescape false %}{{ label|trans }}{% endautoescape %}</label>
{% endspaceless %}
{% endblock %}
From JeanValjean himself :
{% autoescape false %}{{ form.zipcode.vars.label | trans }}{% endautoescape %}
And to generalize this behaviour to your whole app, you can override the form block for labels :
{% block generic_label %}
{% spaceless %}
{% if required %}
{% set attr = attr|merge({'class': attr.class|default('') ~ ' required'}) %}
{% endif %}
<label{% for attrname,attrvalue in attr %} {{attrname}}="{{attrvalue}}"{% endfor %}>
{% autoescape false %}{{ label|trans }}{% endautoescape %}
</label>
{% endspaceless %}
{% endblock %}
To disable the autoespace filter just to render a variable is not the best thing because when you read the code it's not really clear.
So, instead of :
{% autoescape false %}{{ label|trans }}{% endautoescape %}
You can use :
{{ label|trans|raw }}