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.
Related
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>
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.
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.
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 %}
I have this form element I want to render without a label, but I can't find the way...
$builder
->add('gender', 'choice', array(
'expanded' => true,
'choices' => array(
'Male' => 'm',
'Female' => 'f',
)
))
;
some help please, this isn't working:
{% block choice_widget %}
{% spaceless %}
{% for child in form %}
<input type="radio" value="{{ child.get('value') }}">
{% endfor %}
{% endspaceless %}
{% endblock choice_widget %}
I'm getting Array to string conversion
What I wanna do is an image based gender selector, just clicking an image to make the selection.
When using the form component, do not ever render form fields yourself, always rely on the form_ helpers as described in the form documentation.
In your case, this should work:
{{ form_label(form.gender) }}
{{ form_errors(form.gender) }}
{% for choiceFormView in form.gender %}
{{ form_widget(choiceFormView) }}
{% endfor %}