collection form theming symfony2 - forms

I use the following abstract type in my symfony 2 application in order to edit an album
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', 'text')
->add('description', 'textarea')
->add('public', 'checkbox')
->add('lists', 'collection', array(
'attr' => array('data-category' => 'access-right'),
'type' => 'albumListType',
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
)
)
->add('medias', 'collection', array(
'attr' => array('data-category' => 'media'),
'type' => new MediaType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
)
)
;
}
when i display this form i need to display a thumbnail for each medias linked with the article so
i try to overload the mediawidget in order to produce the following html
<div class="row" id="albumtype_media" data-prototype="prototype">
<div class="col-md-3" id="albumtype_media_0">
<img src="path"/>
<input type="hidden" name="albymtype_media[0][path]" value="path"/>
</div>
<div class="col-md-3" id="albumtype_media_1">
<img src="path"/>
<input type="hidden" name="albymtype_media[1][path]" value="path"/>
</div>
</div>
in order to achieve this i use a special form theme to customize the media widget
{% block _medias_widget %}
{% spaceless %}
{% if prototype is defined %}
{% set attr = attr|merge({'data-prototype': form_row(prototype) }) %}
{% endif %}
<div class="row" {{ block('widget_container_attributes') }}>
{{ block('collection_media_rows') }}
{{ form_rest(form) }}
</div>
{% endspaceless %}
{% endblock %}
{% block collection_media_rows %}
{% spaceless %}
{{ form_errors(form) }}
{% for innerform in form %}
{% spaceless %}
<div class="col-md-3" {{ block('widget_attributes') }}>
{% if form.parent is empty %}
{{ form_errors(innerform) }}
{% endif %}
<img src="{{ innerform.vars.value.path }}"/>
{% for child in innerform %}
{{ form_errors(child) }}
{{ form_label(child) }}
{{ form_widget(child) }}
{% endfor %}
</div>
{% endspaceless %}
{% endfor %}
{% endspaceless %}
{% endblock %}
wichh give me the following output
<div class="row" id="albumtype_media" data-prototype="prototype">
<div class="col-md-3" id="albumtype_media" data-prototype="prototype">
<img src="path"/>
<input type="hidden" name="albymtype_media[0][path]" value="path"/>
</div>
<div class="col-md-3" id="albumtype_media" data-prototype="prototype">
<div id="albumtype_media_1">
<input type="hidden" name="albymtype_media[1][path]" value="path"/>
</div>
</div>
as i begin with symfony 2 i don't have a very good understanding at twig and looking at the source code for form_widget doesn't help me neither so if you could explain me how to get the desired result i would be very greatful.

Does your twig template inherit from another template? If not , you should be mindful of block order. Block that are meant to be nested when rendered should be nested.
You cannot define a block as using another block then define that second block afterward.
block "collection_media_rows" should be defined within block "_medias_widget"...

Related

How to change label position in a customized twig form theme

I try to override a symfony form theme. It works, that's the good news!
But I'd like to change the position of the label inside.
My form Builder:
$builder->add('phone', IntegerType::class, [
'label' => 'Telefonnummer',
'constraints' => [
new NotBlank(),
],
'attr' => [
'class' => 'input-field__input',
],
'label_attr' => [
'class' => 'input-field__label',
]
]);
My overridden integer_widget:
{% block integer_widget %}
<div class="input-field">
{% set type = type|default('number') %}
{{ block('form_widget_simple') }}
</div>
{% endblock %}
What I expected (shortened example):
<div class="input-field">
<label>Telefonnummer</label>
<input/>
</div>
What I got:
<label>Telefonnummer</label>
<div class="input-field">
<input/>
</div>
The label comes before the div and isn't inside. But I need it inside!
What i tried (works but in my opinion it is a mess):
{% block integer_widget %}
<div class="input-field">
{% block form_label %}
{% endblock %}
<label class="{{ label_attr.class }}">{{ label }}</label>
{% set type = type|default('number') %}
{{ block('form_widget_simple') }}
</div>
{% endblock %}
This way it looks like I expected. But it's just a workaround because i deleted the origin label by adding an empty 'form_label' block.
Is there a better solution to do this within the rules of symfony/twig?
If all you want is this :
<div class="input-field">
<label for="_input-a">Telefonnummer</label>
<input id="_input-a" name="_name" value="_value">
</div>
Then there is no need to bother yourself with a custom integer_widget
Doing this instead is enough :
<div class="input-field">
{{ form_label(form.phone) }}
{{ form_widget(form.phone) }}
</div>
It will render what you want.

Symfony2 override collection_widget twice in the same template

I have a contacts form with two collections: functions and comments.
The comments collection is very standard and doesn't require any tweaks (just text field and file upload).
But the functions requires to override collection-item because I render each function in a tab.
My issue is that when I customize collection_item widget for the functions, it also tries to apply to the prototype of the comments collection. It fails as the fields are obviously different.
How can I manage that by for example forcing the comments collection to use the standard collection_item widget? Or maybe by passing a variable to the collection_widget block so that it behaves differently depending if it applies to functions or comments...
--EDIT: add twig templates--
Here is my main edit form :
{% extends 'contactsBundle:templates:edit.html.twig' %}
{% form_theme edit_form 'contactsBundle:forms:fonctions.html.twig' %}
{% block form_body -%}
<div class="row">
<div class="col-md-5">
{{ form_row(edit_form.prefix) }}
{{ form_row(edit_form.nom) }}
{{ form_row(edit_form.prenom) }}
</div>
<div class="col-md-5 col-md-offset-2">
{{ form_row(edit_form.referent) }}
{{ form_row(edit_form.groupe) }}
</div>
</div>
{{ form_label(edit_form.fonctions) }}
{{ form_errors(edit_form.fonctions, {attr: {class: 'fonctions-label'}}) }}
{{ form_widget(edit_form.fonctions, {attr: {class: 'fonctions-widget'}}) }}
<ul class="nav nav-tabs">
</ul>
<div class="tab-content">
{% for fonction in edit_form.fonctions %}
{% include 'contactsBundle:forms:fonctions-prototype.html.twig' with {form: fonction.vars.form, index: loop.index} %}
{% endfor %}
</div>
<div class="row">
<div id="commentaire_prototype">
data-prototype="{{ form_widget(edit_form.commentaires.vars.prototype) | e }}"
</div>
{% for commentaire in edit_form.commentaires %}
{{ form_row(commentaires.commentaire) }}
{{ form_row(commentaires.docFile) }}
{% endfor %}
</div>
{% endblock form_body %}
{% block body_end_before_js %}
{{ parent() }}
<script src="{{ asset('bundles/mopabootstrap/js/mopabootstrap-collection.js') }}"></script>
<script src="{{ asset('bundles/contacts/js/forms.js') }}"></script>
{% endblock body_end_before_js %}
Here is my customized collection_widget
{% extends 'contactsBundle:templates:edit.html.twig' %}
{% form_theme edit_form 'contactsBundle:forms:fonctions.html.twig' %}
{% block form_body -%}
<div class="row">
<div class="col-md-5">
{{ form_row(edit_form.prefix) }}
{{ form_row(edit_form.nom) }}
{{ form_row(edit_form.prenom) }}
</div>
<div class="col-md-5 col-md-offset-2">
{{ form_row(edit_form.referent) }}
{{ form_row(edit_form.groupe) }}
</div>
</div>
{{ form_label(edit_form.fonctions) }}
{{ form_errors(edit_form.fonctions, {attr: {class: 'fonctions-label'}}) }}
{{ form_widget(edit_form.fonctions, {attr: {class: 'fonctions-widget'}}) }}
<ul class="nav nav-tabs">
</ul>
<div class="tab-content">
{% for fonction in edit_form.fonctions %}
{% include 'contactsBundle:forms:fonctions-prototype.html.twig' with {form: fonction.vars.form, index: loop.index} %}
{% endfor %}
</div>
<div class="row">
<div id="commentaire_prototype">
{#data-prototype="{{ form_widget(edit_form.commentaires.vars.prototype) | e }}"#}
</div>
{#{{ form_row(edit_form.commentaires) }}#}
{% for commentaire in edit_form.commentaires %}
{{ form_row(commentaires.commentaire) }}
{{ form_row(commentaires.docFile) }}
{% endfor %}
</div>
{% endblock form_body %}
{% block body_end_before_js %}
{{ parent() }}
<script src="{{ asset('bundles/mopabootstrap/js/mopabootstrap-collection.js') }}"></script>
<script src="{{ asset('bundles/contacts/js/forms.js') }}"></script>
{% endblock body_end_before_js %}
And here is my fonctions.prototype.html.twig:
{% if index is not defined %}
{% set index = "__name__" %}
{% endif %}
<div class="collection-item tab-pane" id="{{ index }}">
<div class="row">
<div class="col-md-5">
{{ form_row(form.fonction, {'attr': {'class': 'fonction'} } ) }}
{{ form_row(form.titre) }}
{{ form_row(form.entite, {'attr': {'class': 'entite'} }) }}
{#Todo Add entity address#}
</div>
<div class="col-md-5 col-md-offset-2">
{% if index is defined %}
<div class="form-group">
<a class="btn btn-xs btn-danger coll-del" href="#">
<span class="glyphicon glyphicon-trash"></span>
Supprimer cette Fonction
</a>
</div>
{% else %}
<div class="form-group">
<a class="btn btn-xs btn-danger coll-del" data-collection-remove-btn=".curuba_contactsbundle_contacts_fonction___name___form_group" href="#">
<span class="glyphicon glyphicon-trash"></span>
Supprimer cette Fonction
</a>
</div>
{% endif %}
</div>
</div>
<div class="row">
<div class="col-md-5">
<h4>Contact Professionel</h4>
{{ form_row(form.persoFixe) }}
{{ form_row(form.persoMobile) }}
{{ form_row(form.persoFax) }}
{{ form_row(form.persoMail) }}
</div>
<div class="col-md-5 col-md-offset-2">
<h4>Secrétariat</h4>
{{ form_row(form.assFixe) }}
{{ form_row(form.assMobile) }}
{{ form_row(form.assFax) }}
{{ form_row(form.assMail) }}
</div>
</div>
</div>
Source: http://symfony.com/doc/current/cookbook/form/create_custom_field_type.html
I would go on about this as follows:
Create two form types (Bundle\Form\Type\FunctionType and Bundle\Form\Type\CommentType)
Note down the return value of getName() for each and register your new form types as services, for the following I assume curuba_comment and curuba_function:
#services.yml
services:
bundle.form.type.function:
class: Bundle\Form\Type\FunctionType
tags:
- { name: form.type, alias: curuba_function }
bundle.form.type.comment:
class: Bundle\Form\Type\CommentType
tags:
- { name: form.type, alias: curuba_comment }
Now in your form theme you can add the blocks curuba_comment_widget and curubu_function_widget in which you can call other blocks, e.g. collection_widget.
Then in your Forms Form type do ->add('somefield', 'comment')
Here is how I managed it in a simple way thanks to this post:
symfony2 multiple nested forms prototype
First I change the prototype_name for each collection :
$builder
->add('prefix')
->add('nom')
->add('prenom')
->add('referent')
->add('groupe')
->add('fonctions', 'collection', array(
'type' => new fonctionsType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'label' => 'Fonctions',
'label_attr' => array('class'=>'sub-form-label'),
'prototype_name'=> '__fon_prot__'
))
->add('commentaires', 'collection', array(
'type' => new commentairesType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'label' => 'Commentaires',
'prototype' => true,
'prototype_name'=> '__com_prot__'
))
->add('submit', 'submit', array('label' => 'Enregistrer', 'attr' => array('class' => 'btn btn-lg btn-success')))
Then I add an if statment in my collection_widget :
{% if prototype.vars.name == '__fon_prot__' %}
{% set prototype_markup = include('contactsBundle:forms:fonctions-prototype.html.twig', { 'form': form.vars.form.vars.prototype }) %}
{% else %}
{% set prototype_markup = form_row(prototype) %}
{% endif %}
And that's it.

form_errors(form) symfony2 twig

Using Symfony2.3.4 and Twig
I bet it's an easy peasy for anybody but I just can't get it done.
I'm trying to show only one error alert with always the same message, always at the beginnig of the form, everytime there are errors regardless which field contains the invalid input.
I thought I could do it like this:
//../Professor/Resources/new.html.twig
{% extends 'AdminBundle:Default:admin.html.twig' %}
{% block content -%}
<h1>New professor</h1>
{% if form_errors(form) is not null %} {#<------------------------------------#}
<div class="alert alert-error">
<i class="glyphicon-ban-circle"></i> Message.
</div>
{% endif %}
<div class="row-fluid">
<form id="prof_create" class="form-horizontal sf_admin_form_area" action="{{ path('professor_create') }}"
method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<div class="row-fluid">
<div class="span8"></div>
</div>
<div class="form-actions">
<button class="btn btn-primary">
<i class="icon-ok"></i> {{'Create' | trans}}</button>
<a class="btn" href="{{ path('professor') }}">
<i class="icon-ban-circle"></i> {{'Cancel' | trans }}</a>
</div>
</form>
</div>
{% endblock %}
{% if form_errors(form) is not null %} is not working, meaning:
when I show the create form for the first time before entering any data in the fields,the error alert shows although there is no data in the fields.
I also tried {% if form_errors(form) %} which is also useless but the other way around, it doesn't matter if there are or not errors, the alert just won't show.
There's obviously a lot about form_errors(form) that I don't know.
Appreciate any tips or even completely different solutions.
Thanks
Have you try this ?
{% if form_errors(form.content) is not empty %}
try:
{% if form_errors(form) != '' %}
...
{% endif %}
You will also need to make sure that the error_bubbling option on all of your fields is set to true. If you dont the error only exists on the child. So the main form wouldnt have any errors even though some of the children do.
To set the error bubbling you need to do it to each field:
//Some FormType that you have created
class CustomFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('test', 'text', array('error_bubbling'=>true);
}
}
Your other option is to override the form_errors block like suggested in the accepted answer here:
{% block form_errors %}
{% spaceless %}
{% set a = false %}
{% for child in form.children %}
{% if child.get("errors") %}
{% set a = 'true' %}
{% endif %}
{% endfor %}
{% if a == true %}
<div class="alert">
{% for children in form.children %}
{{ form_errors(children) }}
{% endfor %}
</div>
{% endif %}
{% if errors|length > 0 %}
<ul>
{% for error in errors %}
{{
error.messagePluralization is null
? error.messageTemplate|trans(error.messageParameters, 'validators')
: error.messageTemplate|transchoice(error.messagePluralization, error.messageParameters, 'validators')
}}
{% endfor %}
</ul>
{% endif %}
{% endspaceless %}
{% endblock form_errors %}
try
{% if form.vars.errors|length %}
{% if not form.vars.valid %}
<div class="alert alert-error">
{{ form_errors(form) }}
</div>
{% endif %}
from https://stackoverflow.com/a/17826389/511514

Bootstrap 3: formatted checkboxes with Symfony & Twig

How to create a formatted group of checkboxes as described in the Bootstrap documentation using the Symfony Form Factory and Twig?
Using something like
<div class="row">
<div class="col-lg-4">
{{ form_label(form.sample) }}
</div>
<div class="col-lg-8">
{{ form_widget(form.sample) }}
</div>
</div>
will not result in the needed output:
a) each checkbox within a Bootstrap 3 structure like:
<div class="radio">
<label>
<input type="radio" ... />Option one
</label>
</div>
b) in addition the ability to output the checkboxes in two or more columns if needed:
<div class="row">
<div class="col-lg-6 col-md-6">
<div class="radio"> ... </div>
</div>
<div class="col-lg-6 col-md-6">
<div class="radio"> ... </div>
</div>
</div>
The proper way to do this is to create your own form theme. I will not write the whole thing here, but what matters to you are those:
{% block choice_widget_expanded %}
{% spaceless %}
<div {{ block('widget_container_attributes') }} class="my-form-choices">
{% for child in form %}
{{ form_widget(child) }}
{% endfor %}
</div>
{% endspaceless %}
{% endblock choice_widget_expanded %}
{% block checkbox_widget %}
{% spaceless %}
<div class="checkbox">
<label for="{{ id }}"><input type="checkbox" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />{{ label|trans({}, translation_domain) }}</label>
</div>
{% endspaceless %}
{% endblock checkbox_widget %}
I removed the label rendering from the choice_widget_expanded so I could have the checkbox inside the label tag, just like what you have in your solution. But you can basically do whatever you want in your form theme. You can also overwrite radio_widget if you want to.
If you look closely at the div around the checkboxes, I gave it the class "my-form-choices". You could give it the classes you want. It could be "col-lg-8", like you have, but for me, it makes more sense to have a generic class name, and then use mixins in your own less file. Your less file would look like this:
#import '../../../../../../vendor/twitter/bootstrap/less/bootstrap.less';
.my-form-row {
.make-row();
}
.my-form-choices {
.make-lg-column(8);
}
.my-form-row-label {
.make-lg-column(4);
}
But that's up to you. You don't have to do this if you don't want to. Finally, you use your theme by starting the twig for your page like this:
{% extends 'MyOwnBundle::layout.html.twig' %}
{% form_theme form 'MyOwnBundle:Component:formtype.html.twig' %}
And you display the row simply like that (the field I used in my test is availability, yours is sample):
{{ form_row(form.availability) }}
I've tried that (with Symfony 2.4), and it works. The output is something like that:
<div class="my-form-row">
<div class="my-form-row-label">
<label class="required">Availability</label>
</div>
<div class="my-form-choices" id="myown_website_contactmessage_availability">
<div class="checkbox">
<label for="myown_website_contactmessage_availability_0">
<input type="checkbox" value="morning" name="myown_website_contactmessage[availability][]" id="myown_website_contactmessage_availability_0">
Morning
</label>
</div>
<div class="checkbox">
<label for="myown_website_contactmessage_availability_1">
<input type="checkbox" value="afternoon" name="myown_website_contactmessage[availability][]" id="myown_website_contactmessage_availability_1">
Afternoon
</label>
</div>
<div class="checkbox">
<label for="myown_website_contactmessage_availability_2">
<input type="checkbox" value="evening" name="myown_website_contactmessage[availability][]" id="myown_website_contactmessage_availability_2">
Evening
</label>
</div>
</div>
</div>
Also notice that I do not have sub-rows, like you have in your solution. In fact, your solution goes beyond the question you were asking in the first place.
EDIT: here's a solution for having multiple columns
To have multiple columns, here is a quick solution. First, the form theme could be something like this:
{% block choice_widget_expanded %}
{% spaceless %}
<div class="my-form-choices-container">
<div {{ block('widget_container_attributes') }} class="my-form-choices">
{% for child in form %}
{{ form_widget(child) }}
{% endfor %}
</div>
</div>
{% endspaceless %}
{% endblock choice_widget_expanded %}
{% block checkbox_widget %}
{% spaceless %}
<div class="my-form-choice">
<div class="checkbox">
<label for="{{ id }}"><input type="checkbox" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />{{ label|trans({}, translation_domain) }}</label>
</div>
</div>
{% endspaceless %}
{% endblock checkbox_widget %}
And then your less file would look like this:
#import '../../../../../../vendor/twitter/bootstrap/less/bootstrap.less';
.my-form-row {
.make-row();
}
.my-form-row-label {
.make-lg-column(4);
}
.my-form-choices-container {
.make-lg-column(8);
}
.my-form-choices {
.make-row();
}
.my-form-choice {
.make-md-column(6);
}
In this solution, you change the number of columns by changing the size of the columns. The cells should stack neatly. In this case, it is better to compile less (I won't explain that here). I have tried this solution, and it works well. The advantage of using less in this case, is that you can use the same form theme on multiple pages, and change the number of columns just by having a different "less" file for each of your pages.
You need to access to the form vars which contain the information about the checkboxes:
form.sample.vars.form.children
now you can loop through the checkboxes and access the values:
{% for children in form.sample.vars.form.children %}
<div class="checkbox>
<label>
<input type="checkbox" name="{{ children.vars.full_name }}" id="{{ children.vars.id }}" value="{{ children.vars.value }}"{% if children.vars.data %} checked="checked"{% endif %} />
{% if children.vars.label is defined %}
{{ children.vars.label|trans }}
{% else %}
{{ children.vars.value|capitalize|trans }}
{% endif %}
</label>
</div>
{% endfor %}
I place this code in a Twig template and add some logic to create rows with variable columns, so it look like this:
{% set cols = columns|default(1) %}
{% set i = 1 %}
{% for children in childrens %}
{% if i == 1 %}<div class="row">{% endif %}
<div class="col-lg-{{ 12/cols }} col-md-{{ 12/cols }}">
<div class="checkbox {{ class|default('') }}">
<label>
<input type="checkbox" name="{{ children.vars.full_name }}" id="{{ children.vars.id }}" value="{{ children.vars.value }}"{% if children.vars.data %} checked="checked"{% endif %} />
{% if children.vars.label is defined %}
{{ children.vars.label|trans }}
{% else %}
{{ children.vars.value|capitalize|trans }}
{% endif %}
</label>
</div>
</div>
{% set i = i+1 %}
{% if i > cols %}
</div>
{% set i = 1 %}
{% endif %}
{% endfor %}
{% if i != 1 %}</div>{% endif %}
now you can include this checkbox template where you need it:
<div class="row">
<div class="col-lg-4">
{{ form_label(form.sample) }}
</div>
<div class="col-lg-8">
{% include 'checkbox.twig' with {childrens:form.sample.vars.form.children, columns:2} only %}
</div>
</div>
the example above will return well formatted Bootstrap 3 output with checkboxes in two columns like this:
<div class="row">
<div class="col-lg-4">
<label class="required">Veranstalter</label>
</div>
<div class="col-lg-8">
<div class="row">
<div class="col-lg-6 col-md-6">
<div class="checkbox ">
<label><input type="checkbox" name="form[sample][]" id="form_sample_0" value="DUMMY">Dummy</label>
</div>
</div>
<div class="col-lg-6 col-md-6">
<div class="checkbox ">
<label><input type="checkbox" name="form[sample][]" id="form_sample_1" value="DUMMY_1">Dummy 1</label>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6 col-md-6">
<div class="checkbox ">
<label><input type="checkbox" name="form[sample][]" id="form_sample_2" value="DUMMY_2">Dummy 2</label>
</div>
</div>
</div>
It's easy to use and will also work for radio buttons - just replace the class "checkbox" with "radio".
Ran into this issue today and thought I'd share my solution. I already had a form input override file, but didn't like what I found elsewhere. So wrote a form_label block override like so.
{% block form_label -%}
{% if label is not sameas(false) -%}
{% if not compound -%}
{% set label_attr = label_attr|merge({'for': id}) %}
{%- endif %}
{% if required -%}
{% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %}
{%- endif %}
{% if label is empty -%}
{% set label = name|humanize %}
{%- endif -%}
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>{% if 'checkbox' in block_prefixes %}{{ form_widget(form) }}{% endif %}{{ label|trans({}, translation_domain) }}</label>
{%- endif %}
{%- endblock form_label %}
Then the form_row block like so:
{% block form_row %}
{% spaceless %}
{% if 'checkbox' not in block_prefixes %}
<div class="form-group">
{{ form_label(form) }}
{{ form_errors(form) }}
{% if 'datetime' not in block_prefixes %}
{{ form_widget(form, { 'attr': {'class': 'form-control'} }) }}
{% else %}
{{ form_widget(form) }}
{% endif %}
</div>
{% else %}
{% import _self as forms %}
<div class="checkbox">
{{ form_label(form) }}
</div>
{% endif %}
{% endspaceless %}
{% endblock %}
I choose this method because it allowed me to continue to use the basic form(form) method in templates. Hope this helps you.
If you're looking for the simple version of this answer (ie you've already applied the bootstrap_3_layout theme to your form and just want to apply custom label text)
{{ form_widget( form.field, { 'label': 'Custom Label Text' } ) }}

Symfony2 (twig): pass array into form functions

I am trying to implement a form_function that can accept an array of forms.
FormExtension looks like this:
[...]
'form_controls_row' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\RenderBlockNode', array('is_safe' => array('html'))),
[...]
My field.html.twig would be this:
{% extends 'MopaBootstrapBundle:Form:fields.html.twig' %}
{# import "_self" as the form theme #}
{% form_theme form _self %}
{# make the form fragment customization #}
{% block form_controls_row %}
{% spaceless %}
<div class="controls controls-row">
{% for element in form %}
{{ form_row(element, _context) }}
{% endfor %}
<div>
{% endspaceless %}
{% endblock form_controls_row %}
And my form itself would look like that:
{% form_theme form 'MyBundle::fields.html.twig' %}
<div class="well">
<form action="{{ path('fos_user_registration_register') }}" {{ form_enctype(form) }} method="POST" class="fos_user_registration_register">
{{ form_controls_row([form.firstName, form.lastName]) }}
{{ form_rest(form) }}
</form>
</div>
But everytime I pass in an array ([form.firstName, form.lastName]) into form_controls_row I get an exception.
Is there any way to allow arrays?
Or is there any better solution for my purpose?