Twig: set a variable inside a loop, use it outside that loop - php

I'm trying to define driverid, using set, as a var in for driver in assigned.driver cycle for use later. See below what I'm doing:
{% for key, assigned in pgn %}
<tr id="device-{{ assigned.id }}">
<td>{{ assigned.imei }}</td>
<td>{{ assigned.description }}</td>
<td>
{% for driver in assigned.driver %}
{{ driver.driver.id }} {# check if driver.driver.id has values testing purposes - delete me #}
{% set driverid = driver.driver.id %}
{% if driver.driver.name != "" %}
{% if driver.driver.name %}
{{ driver.driver.name }}
{% else %}
-
{% endif %}
{% endif %}
{% endfor %}
</td>
<td>
<button class="btn btn-xs btn-default"
onclick="openAlert({{ assigned.id }}, {{ driverid }}, 'unlink')"
data-original-title="{{ "devices.actions.unlink"|trans }}"
title="{{ "devices.actions.unlink"|trans }}">
<i class="fa fa-times"></i>
</button>
<button class="btn btn-xs btn-default"
onclick="openAlert({{ assigned.id }}, null, 'delete')"
data-original-title="{{ "button.delete"|trans }}"
title="{{ "button.delete"|trans }}">
<i class="fa fa-times"></i>
</button>
</td>
</tr>
{% endfor %}
But I get this error:
Variable "driverid" does not exist in
/var/www/html/src/Device/DeviceBundle/Resources/views/List/listDevices.html.twig
at line 74
What's the right way to set that var to use later on openAlert() call? Or in others words how I get the driver.driver.id to pass it as a parameter to openAlert() function?

As they say here, this is not a bug, it's a feature: variables defined inside a loop are scoped to that loop.
But don't worry, you can define the var outside the loop and assign it inside, like this:
{% set driverid = '' %} {# <-- add this line: default empty value #}
{% for driver in assigned.driver %}
...
{% set driverid = driver.driver.id %}
this should be enough to make it work.

If assigned.driver is empty, then the for loop is never executed so the variable won't be defined. What you need to do is to initialize this variable outside of the loop: {% set driverid = null %}

Related

count key in twig symfony

i try to simply count object into a city
enter image description here
in paris, i have 5 object, i don't want show 11111 but just 5,
that my code
{% set newAnnounceCity = [] %}
{% for item in announceCity %}
{% if item.infoCity is not null %}
{% if item.infoCity.city not in newAnnounceCity %}
<span class=" font-semibold mr-2 text-left flex-auto">
<a href="{{path('app_city_show',{slug: item.infoCity.slug})}}">
<button class=" m-2 p-2 pl-5 pr-5 bg-transparent border-2 border-red-500 text-red-500 text-lg rounded-lg hover:bg-gradient-to-b hover:from-red-600 hover:to-pink-500 hover:text-gray-100 focus:border-4 focus:border-red-300">
{{ (item.infoCity.city) }}
{% for key in item.infoCity.announce|keys %}
{{key|length }}
{% endfor %}
{% set newAnnounceCity = newAnnounceCity|merge([item.infoCity.city]) %}
</button>
</a>
</span>
{% endif %}
{% else %}
{% endif %}
{% endfor %}
someone can help me
i try to count an keys object
It's a bit hard to guess without a sample structure of your input array, but maybe try replacing
{% for key in item.infoCity.announce|keys %}
{{key|length }}
{% endfor %}
with simply
{{ item.infoCity.announce|length }}

How use rendered variables in a foreach Symfony 2 ~ twig

its not the first time I met this issue and I cannot fix it!
Actually, I'm rendering a template with a controller who give to the rendered page many variables. One of them, called $categories, in it, There are many of Category objectes so, one of them its a Collection what references to another Category.
The point is, I'm try to do this code, but obviusly I get an error because im trying to print as a String a Collection
{% for category in categories %}
<tr>
<td>{{ category.name }}</td>
<td>{{ category.description }}</td>
<td>{{ category.isPublic }}</td>
<td>{{ category.parentCategory }}</td>
<td>{{ category.childrens }}</td>
<td>
<i class="fa fa-pencil-square-o" aria-hidden="true"></i>
<i class="fa fa-times" aria-hidden="true"></i>
</td>
</tr>
{% endfor %}
So, I decided to try something like:
{% for category in categories %}
<tr>
<td>{{ category.name }}</td>
<td>{{ category.description }}</td>
<td>{{ category.isPublic }}</td>
<td>{{ category.parentCategory }}</td>
<td>
{% for children in {{ category.childrens }} %}
children.name
{% endfor %}
</td>
<td>
<i class="fa fa-pencil-square-o" aria-hidden="true"></i>
<i class="fa fa-times" aria-hidden="true"></i>
</td>
</tr>
PROBLEM:
I don't know how use a rendered variable in a foreach, im gettin this error:
A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "punctuation" of value "{" in AppBundle:admin:category/listCategory.html.twig at line 55.
{{ }} or {% %} or {# #} are Twig's open and close tags. Similair to <?php ?> in PHP code. Once you use an open tag, the text is parsed by Twig until the close tag is found (this is also how things are done in PHP, the only difference is that Twig has a different tag to echo stuff).
Once open, you don't have to reopen it again. You don't want to dump category.childrens, you want to use it in the for loop. So instead of doing: {% for children in {{ category.childrens }} %}, use {% for children in category.childrens %}.
(you can compare this to PHP, doing
<?php foreach (<?php echo $category->childrens ?> as $children) { ?>
doesn't make much sense).
The error probably comes from this line:
{% for children in {{ category.childrens }} %}
This is not a valid syntax, the {{ }} can't be used inside another Twig tag.
The following code should work:
{% for children in category.childrens %}
To be honest I have 0 experience with the twig templating langauge, so I may be wrong here, but my experience with other languages tells me the following code:
{% for children in {{ category.childrens }} %}
children.name
{% endfor %}
Should probably look like this:
{% for children in category.childrens %}
{{ children.name }}
{% endfor %}

Error in nested form and twig display

I have a problem with errors display in my twig templates.
Here is my twig with one nested form form.pictures :
{{ form_start(form) }}
{% if not form.vars.valid %}
<div class="flash-errors-wrapper">
{{ form_errors(form) }}
<div class="form-errors">{{ form_errors(form.pictures) }}</div>
</div>
{% endif %}
{% for formChild in form.pictures %}
<div class="child">
{% if not formChild.vars.valid %}
<div class="flash-errors-wrapper">
{{ form_errors(form) }}
<div class="form-errors">{{ form_errors(form.picture) }}</div>
<div class="form-errors">{{ form_errors(form.caption) }}</div>
</div>
{% endif %}
{{ form_widget(formChild.picture) }}
{{ form_widget(formChild.caption) }}
</div>
{% endfor %}
{{ form_end(form) }}
After submission, when a child form is non valid, my parent form is not valid too.
Problem is that it display empty div on top like :
<div class="flash-errors-wrapper">
<div class="form-errors"></div>
</div>
I don't want that because css exist on flash-errors-wrapper class so style is applied.
Any ideas?
You certainly need to check if one child form is not valid when you check if the parent form is valid. One way to do it would be (Untested, it may need some adaptation):
{% if not form.vars.valid %}
{% set all_childs_valid = True %}
{% for formChild in form.pictures %}
{% if not formChild.vars.valid %}
{% set all_childs_valid = False %}
{% endif %}
{% endfor %}
{% if all_childs_valid %}
<div class="flash-errors-wrapper">
{{ form_errors(form) }}
<div class="form-errors">{{ form_errors(form.pictures) }}</div>
</div>
{% endif %}
{% endif %}
I usually display form errors just as described in docs:
{% if errors|length > 0 %}
<ul>
{% for error in errors %}
<li>{{ error.message }}</li>
{% endfor %}
</ul>
{% endif %}

Symfony2 displaying dynamically values from array to twig

I have a function in which I count the final price of each product and I save it in an array. Now when I want do display the values I am stuck at how to display all of them dynamicaly.
This is the function:
public function getTotal($items)
{
$total = array();
foreach($items as $key=>$item){
$total[$key] = $item->getPrice() - $item->getDiscount() + $item->getValue();
}
return $total;
}
All of the methods getValue, getDiscount and etc are working.
This is how I try o display:
{{ getTotal(product)[key]}}
The problem is that when I write for example {{ getTotal(product)[0]}} or {{ getTotal(product)[1]}} and etc i get the correct value, but only of 1 product. I need to get the values from all of them.
If i do {{ getTotal(product)[key]}} im getting a strange error:
Key "12" for array with keys "0, 1" does not exist in MpShopBundle:Frontend:product_summary.html.twig at line 89
I have no idea why the key is equal to 12? Maybe I have to write something different?
UPDATE
Thank you for the answers, I didnt even think about looping with twig, but I am finally getting some values. However, I dont know why but the twig loop assigns both values for each product.
This is how it should be:
Product1 : 0(key):145(value)
Product2 : 1:415
But this is how it is:
Product1 : 0:145 1:415
Product2 : 0:145 1:415
This is the twig:
{% if product is defined %}
{% for key, item in cart %}
{% for item in product %}
<tr>
<td> <img width="60" src="{{ asset('bundles/mpFrontend/assets/products/4.jpg') }}" alt=""/></td>
<td>{{ item.model }}</td>
<td>
<div class="input-append"><input class="span1" style="max-width:34px" placeholder="1" id="appendedInputButtons" size="16" type="text">
<button class="btn" type="button"><i class="icon-minus"></i></button>
<button class="btn" type="button"><i class="icon-plus"></i></button>
<button class="btn btn-danger" type="button"><a href="{{ path('cart_remove', {'id': key}) }}"><i class="icon-remove icon-white"></i></button>
</div>
</td>
<td>{{ item.price }}</td>
<td>{{ item.discount }}</td>
<td>{{ item.value }}</td>
{% if getTotal(product) is iterable %}
{% for key, sum in getTotal(product) %}
<td>{{ key }}:{{ sum }}</td>
{% endfor %}
{% endif %}
</tr>
{% endfor %}
Use twig for loop:
{% for total in getTotal(product) %}
{{ total }}
{% endfor %}
You can use the twig for loop.
Example:
{% if getTotal(product) is iterable %}
{% for key, sum in getTotal(product) %}
{{ key }}:{{ sum }}
{% else %}
empty array
{% endfor %}
{% endif %}
You shouldn't use a loop, and move your function from an external to a method of the product class.
Instead of loop:
<td>{{ product.total }}</td>
New function:
class Product {
...
public function getTotal()
{
return $this->getPrice() - $this->getDiscount() + $this->getValue();
}
}

For loop with a passed parameter to twig in Symfony2

I am a beginner in symfony2 .
I have a problem in a loop with a passed parameter to twig tepmlate: (show nbr stars )
{% for i in 0..4 %}
<span class="glyphicon glyphicon-star"></span>
{% endfor %}
The number of iteration (nbr) is passed as a parameter, I have tested this , but not working.
{% for i in 0..{{nbr}} %}
<span class="glyphicon glyphicon-star"></span>
{% endfor %}
Say you want to iterate with a given parameter
return $this->render('AcmeFoo::foo.html.twig', array(
'number' => 42
));
Your TWIG template should look like
{% for i in 0..number %}
{{ i }}
{% endfor %}
This also works for runtime-set variables
{% set number = 5 %}
{% for i in 0..number %}
{{ i }}
{% endfor %}

Categories