Sf/Twig - count number of property with same value - symfony

I just want to display on a twig view the number of a property with a value defined like
<div class="list-group">
{% for ticket in tickets %}
{% if ticket.statut == 'En attente' %}
{{ loop.index }}
{{ ticket.statut }}
<div class="d-flex justify-content-start"><i class="fas fa-ticket-alt"></i> {{ ticket.getNomProduit }}</div>
{% endif %}
{% endfor %}
</div>
but i got the right number(2) but i would only display the number of this specific ticket with value "En attente"

If I had to implement such a thing, I would do it somewhere in the PHP controller, something like this:
// In the controller:
$ticketsEnAttente = array_filter($tickets,
function($ticket) {
return $ticket['statut'] === 'En attente';
}
);
return $this->render('my_template.html.twig', [
'tickets_en_attente' => $ticketsEnAttente,
]);
Then it is trivial to show the count and the different tickets in Twig, something like:
<div>
{{ tickets_en_attente | length }} tickets en attente:
</div>
{% for ticket in tickets_en_attente %}
{{ loop.index }}
<div class="d-flex justify-content-start">
<a href="{{ path('ticket', {id:ticket.id}) }}" class="list-group-item list-group-item-action active">
<i class="fas fa-ticket-alt"></i>
{{ ticket.getNomProduit }}
</div>
</a> {# NOTE: there is an html error in your code, </div> and </a> are inverted #}
{% endfor %}
The only difference here is that the loop index will not be the same as the original code you gave, because it takes only into account the filtered list.
In a general way, it is a good idea to put as few as possible complex computations in the twig templates. Controllers and services are a better place for it.
EDIT
To answer to your comment, if there are several statuses, you can create a variable which groups tickets by their status:
// In your controller:
// Mock data:
$tickets = [
[ 'id' => 1, 'statut' => 'Fermé' ],
[ 'id' => 2, 'statut' => 'En attente' ],
[ 'id' => 3, 'statut' => 'Ouvert' ],
[ 'id' => 4, 'statut' => 'En attente' ],
];
// Group tickets by status:
$ticketsByStatus = [];
foreach ($tickets as $ticket) {
$ticketsByStatus[$ticket['statut']][] = $ticket;
}
// This is equivalent to writing this by hand:
$ticketsByStatus = [
'Fermé' => [
[ 'id' => 1, 'statut' => 'Fermé' ],
],
'En attente' => [
[ 'id' => 2, 'statut' => 'En attente' ],
[ 'id' => 4, 'statut' => 'En attente' ],
],
'Ouvert' => [
[ 'id' => 3, 'statut' => 'Ouvert' ],
],
];
return $this->render('default/index.html.twig', [
'tickets_by_status' => $ticketsByStatus,
]);
Then you can iterate over each status in the template (or access them manually if you prefer), something like this:
{% for status in tickets_by_status|keys %}
<h4>{{ status }}:</h4>
<ul>
{% for ticket in tickets_by_status[status] %}
<li>
{{ ticket.id }}
{# {{ ticket.getNomProduit }} #}
</li>
{% endfor %}
</ul>
{% endfor %}
Up to you to make this fit to your own needs.

Try this:
<div class="list-group">
{% set count = 0 %}
{% for ticket in tickets %}
{% if ticket.statut == 'En attente' %}
{{ loop.index }}
{{ ticket.statut }}
<div class="d-flex justify-content-start"><i class="fas fa-ticket-alt"></i> {{ ticket.getNomProduit }}</div>
{% set count = count + 1 %}
{% endif %}
{% endfor %}
{{ count }} Total File En attente
</div>

Related

How do i get Subcategory Name from twig/timber file?

i can't find the {% if categoryName %} Code for parent / subcategory.
Please See my Screenshots and Codes:
Actually:
Should be like this:
Backend:
My Shortcode for those Views atm:
[events category="66"]
ShortcodeEvents.php File:
<?php
namespace WpTheme\Shortcodes\Module;
use WpTheme\Shortcodes\ShortcodeModule;
class ShortcodeEvents extends ShortcodeModule
{
/**
* #param $atts
*
* #return mixed
*/
public function handle($atts, $content = null) {
extract(shortcode_atts([
'category' => false,
'limit' => - 1,
'parent' => $sub_category->cat_ID,
], $atts));
$args = [
'posts_per_page' => $limit,
];
if ($category) {
$category = collect(explode(',', $category))->map(function ($value) {
return trim($value);
})->filter()->toArray();
$args = collect($args)->merge([
'tax_query' => [
[
'taxonomy' => 'event-category',
'field' => 'term_id',
'terms' => $category,
],
],
])->toArray();
$events = app(\WpTheme\PostTypes\Repository\Event::class)->all($args);
$categoryName = get_term(array_shift($category), $taxonomy)->name;
} else {
$events = app(\WpTheme\PostTypes\Repository\Event::class)->allGroupedByCategory();
}
return $this->renderView('shortcodes/events.twig', compact('events', 'categoryName'), false);
}
}
My twig File:
{% if events %}
{% if categoryName %}
<h2>{{ categoryName }}</h2>
<hr class="mt-0 mb-8">
{% endif %}
{% for parentTerm in events %}
<div class="{{ loop.index == 1 ? 'mb-default' : 'mt-default' }}">
<div class="mb-8 mb-lg-12 mb-xl-16">
<h2>{{ parentTerm.name }}</h2>
{% if parentTerm.description %}
<p>{{ parentTerm.description }}</p>
{% endif %}
</div>
{% for childTerm in parentTerm.childTerms %}
<div class="mb-8 mb-lg-12">
<h3>{{ childTerm.name }}</h3>
{% for event in childTerm.events %}
{% set index = random() %}
<div class="my-4">
<b-button variant="unstyled" v-b-toggle.accordion-{{ index }} class="accordion-trigger">
<span class="plus"></span>
<h4>{{ event.title }}</h4>
</b-button>
<b-collapse id="accordion-{{ index }}" accordion="my-accordion" role="tabpanel">
<div class="py-4 py-lg-6">
{% set speaker = event.meta('speaker') %}
{% if speaker %}
<p>
{{ speaker.title }}
</p>
{% endif %}
{% if event.meta('dates') %}
<table class="table-responsive-md">
<thead>
<tr>
<th>{{ function('trans', 'global.date') }}</th>
<th>{{ function('trans', 'global.place') }}</th>
<th>{{ function('trans', 'global.topic') }}</th>
</tr>
</thead>
<tbody>
{% for date in event.meta('dates') %}
<tr>
<td class="text-nowrap">{{ date.date|date("d.m.Y") }}</td>
<td class="text-nowrap">{{ date.location }}</td>
<td>{{ date.topic }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</div>
</b-collapse>
</div>
{% endfor %}
</div>
{% endfor %}
</div>
{% endfor %}
{% endif %}
I found out, that at least i can get some Items from Subcategory if i use:
{{ parentTerm.title }} instead of {{ event.title }}
{% if parentTerm.meta('dates') %} instead of {% if event.meta('dates') %}
But parentTerm.category or parentTerm.categoryName seems not working.
Any Ideas?
#Alorsons I want to make sure you're aware that subcategories/child terms naturally come through any Timber\Term object via {{ term.children }} — this returns an array of other Timber\Term objects representing any children (subcategories for the category taxonomy — but will work with any hierarchical taxonomy)

Symfony 3 nested collection templating with Twig

how i can templating nested collection?.
I create templating parent collection with block:
{% block _group_match_groupMatchType_entry_row %}
In this block i have collection:
<div class="js-collection-parrent round text-right" data-prototype="{{ form_row(form.matchResult.vars.prototype)|e('html_attr') }}">
How i can get every entry row of matchResult collection which has parent collection groupMatchType?
GroupMatchType
$builder
->add('groupMatchType', CollectionType::class, [
'entry_type' => MatchType::class,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false
])
MatchType
$builder
->add('matchResult', CollectionType::class, [
'entry_type' => MatchResultType::class,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false
])
And view
{% block _group_match_groupMatchType_entry_row %}
<div class="js-collection-parrent round text-right" data-prototype="{{ form_row(form.matchResult.vars.prototype)|e('html_attr') }}"></div>
{% endblock %}
I have to find name of above block (maybe like _group_match_groupMatchType_entry_row_matchResult_entry_row)
Ok i solved that. The block should be named
_group_match_groupMatchType_entry_matchResult_entry_row
Getting all sub-elements in a form on twig is simple:
{% for element in form.elements %}
{# Do something with this element #}
{# But think that it will represent the form element #}
{% endfor %}
real example:
{% for movie in form.movies %}
{{ form_widget(movie.title, {'attr' : {'class':'form-control'}}) }}
{{ form_row(movie.id) }}
{% endfor %}
Don't really know if is what you need, but I believe it's an approach to what you mean.

Render custom attribute KNP Menu

Is there a way to render a custom attribute in the KNP Menu Bundle, something like this:
$menu = $factory->createItem(Role::ROLE_PROGRAM_EVENT_PLANNER, array(
'route' => 'show_form_events',
'attributes' => array('class' => 'menu pe_planner'),
'extra' => array(
'content' => 'my custom content'
)
));
I have overriden the linkElement by adding an extra div after the a-tag. In that div I would like to render extra content
{% block linkElement %}
{% import _self as knp_menu %}
<a href="{{ item.uri }}"{{ knp_menu.attributes(item.linkAttributes) }}>{{ block('label') }}</a>
{% if item.hasChildren == false %}
<div class="custom">{{ item.getExtra('content') }}</div>
{% endif %}
{% endblock %}
Actually i had to do quite the same for today ;)
MenuBuilder
$menu->addChild(
'Dashboard',
array(
'route' => 'dashboard',
'attributes' => array(
'class' => 'navigation-entry'
),
'extras' => array(
'icon' => '6'
)
)
);
menuTemplate
{% block linkElement %}
{% import "knp_menu.html.twig" as macros %}
<a href="{{ item.uri }}"{{ macros.attributes(item.linkAttributes) }}>
<span class="icon">{{ item.getExtra('icon') }}</span>
<span class="entry">{{ block('label') }}</span>
</a>
{% endblock %}
Dont be confused be the icon content because i use an icon font.

Access collection field in twig

How can I access a field in collection in twig
$builder
->add('name', 'text', array('required' => false))
->add('email', 'collection', array(
'type' => new UsersEmailAddressesType(),
'allow_add' => true
))
UserEmailAddressesType has two fields name and email, how can I access email field in twig ?
In the symfony cookbook there is an example on how to embed collections in forms. The solution there looks like this (adapted to your form example):
<ul>
{% for email in form.email %}
<li>{{ form_row(email.address) }}</li>
{% endfor %}
</ul>
Since you want to place the inputs next to each other you might want to check whether the loop.index is odd, even or divisibleby() for example like this:
{% for email in form.email %}
{% if loop.index is odd %}
<li class="float-left">
{% else %}
<li class="float-right">
{% endif %}
{{ form_row(email.address) }}</li>
{% endfor %}

Grouping checkboxes in Symfony2

It seems that Symfony2 Form component does not handle this common case. Below is what I want in my html
The code looks like :
->add('code', 'choice', array(
'choices' => array(
'Food' => array('pizza', 'burger', 'icecream'),
'Music' => array('poney', 'little', 'pocket'),
),
'multiple' => true,
'expanded' => true,
'required' => true
));
Which gives in reality the wrong output :
It's wierd because the case with expanded => false is correctly handled
How to handle that case please ?
Ok so here's the form_theme solution for this
{% block _user_code_widget %}
<div {{ block('widget_container_attributes') }}>
{% for name, choices in form.vars.choices %}
<ul>
<li class="checkbox_category">
<input type="checkbox" class="checkallsub" /> {{ name }}
</li>
{% for key,choice in choices %}
<li class="indent">
{{ form_widget(form[key]) }}
{{ form_label(form[key]) }}
</li>
{% endfor %}
</ul>
{% endfor %}
</div>
{% endblock %}
Of course the extra js layer is missing, but you get the idea.

Resources