How use rendered variables in a foreach Symfony 2 ~ twig - php

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 %}

Related

Symfony get username from userid in twig template

I'm trying to make a table with all entities from the database. This works fine, but in the entity is only the user id saved.
How I can fetch the username?
{% for invite in invites %}
<tr>
<td>{{ invite.code}}</td>
<td>{{ invite.creator }}</td> {# This line returns the user id, but how I can get the username? #}
<td>{{ invite.creationdate|format_datetime(locale='de') }}</td>
<td><a class="btn btn-danger btn-sm" href="{{ path('admin.invite.delete', {'id': invite.id}) }}">
<i class="fas fa-trash">
</i>
Delete
</a>
</td>
</tr>
{% endfor %}
If invite.creator is object, then you can access to its properties.
{{ invite.creator.username }} {# name property of User::class #}
If it is id only, then you need to pass array 'userIdToUser' into twig from your contoller
{{ userIdToUser[invite.creator] }}

translate tabledata in twig

I fill my table with data in this way
<tbody>
{% for post in posts %}
<tr>
<td>{{ post.title }}</td>
<td>{{ post.status }}</td>
</tr>
{% endfor %}
</tbody>
I need translate values from status, but it does not work. post.status has only 2 values in database PO_DRAFT and PO_ACCEPT and I need it translate. Is it possible?
I tried in this way but it is wrong
<td>{% trans %}{{ post.status }}{% endtrans %}</td>
Twig's i18n documentation mentions a trans filter, so maybe this would work?
{{ post.status | trans }}

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();
}
}

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

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 %}

Symfony2: deprecated get in FormView replacement?

In versions < 2.3, the attribute
data-prototype="{% filter escape %}{% include 'ManaClientBundle:Member:member_prototype.html.twig' with {'form': form.members.get('prototype')} %}{% endfilter %}"
allowed the prototype to display as a row of cells. In 2.3, of course, this line generates the error
Method "get" for object "Symfony\Component\Form\FormView" does not
exist
Per UPGRADE-2.1.md, get is deprecated. It cannot be replaced by the suggested vars as it produces a similar error. How can I (easily?) render the prototype as before in 2.3? Using
data-prototype="{{ form_widget(form.members.vars.prototype)|e }}"
does not provide a useful solution regardless of div or table settings for twig:resources:form in config.yml.
prototype
<tr id="member-form">
<td><input class="smallform" type="radio" name="household[isHead]" value="__name__"></td>
<td>{{ form_widget(form.include, {'attr': {'class':'smallform'}}) }}</td>
<td>{{ form_widget(form.fname, {'attr': {'class':'smallform'}}) }}</td>
<td>{{ form_widget(form.sname, {'attr': {'class':'smallform'}}) }}</td>
<td>{{ form_widget(form.dob, {'attr': {'class':'smallform'}}) }}</td>
<td>{{ form_widget(form.sex, {'attr': {'class':'smallform'}}) }}</td>
<td>{{ form_widget(form.ethnicity, {'attr': {'class':'smallform'}}) }}</td>
<td><a id="removeTr" class="smallbutton" href="#" onclick="removeTr(this)">Remove</a>
Replace form.members.get('prototype') with form.members.vars.prototype.
Could have been a whole lot clearer what to do, but fewer than infinite monkeys found a solution.
Above won't work for me when extending block.
In 2.3.7 at least, I was able to access vars like:
{% block form_row %}
{{ form.vars.value }}
.....
{% endblock %}
And when an ArrayCollection like:
{% block sonata_type_collection_widget %}
{% for child in form %}
{{ child.vars.form.vars.value.name }}
{% endfor %}
{% endblock %}
Hope that helps someone.

Categories