I am trying to get rid of repeating layouts in twig for symfony2 forms Currently my layout looks something like :
<form name="step2" method="post" action="" class="productForm">
<h2>Step2:</h2>
<div id="step2">
<div class="form-group">
<div class="form-widget">
<div id="step2_client1">
<div class="form-group"><label class="control-label required" for="step2_client1_clientTitle">Client 1 title:</label>
<div class="form-widget"><select id="step2_client1_clientTitle" name="step2[client1][clientTitle]" class="form-control">
<option value="Mr">Mr</option>
<option value="Mrs">Mrs</option>
<option value="Miss">Miss</option>
<option value="Ms">Ms</option>
<option value="Dr">Dr</option>
<option value="Sir">Sir</option>
</select></div>
</div>
<div class="form-group"><label class="control-label required" for="step2_client1_firstName">Client 1 first name:</label>
<div class="form-widget"><input type="text" id="step2_client1_firstName" name="step2[client1][firstName]" required="required" class="form-control">
</div>
</div>
<div class="form-group"><label class="control-label required" for="step2_client1_surname">Client 1 last name:</label>
<div class="form-widget"><input type="text" id="step2_client1_surname" name="step2[client1][surname]" required="required" class="form-control"></div>
</div>
</div>
</div>
</div>
...
<div class="form-group form-group-submit">
<div class=""><a id="step2_save" class="has-spinner btn btn-default btn-submit"><span class="spinner"><i class="fa fa-spinner fa-spin"></i></span>Complete the quote
</a></div>
</div>
<input type="hidden" id="step2__token" name="step2[_token]" class="form-control" value="xxx"></div>
</form>
And I have a dirty js script to fix my layout in the way I want it to showup but this is, as said, dirty. So I was wondering if someone can help me alter my twig file to only show form-group and form-widget css classes for children elements and not for the parents.
The dirty js script:
$('.form-group').each(function(e){
if($(this).parents('.form-group').length) {
var $realGroup = $(this).parents('.form-group');
$realGroup.toggleClass('form-group');
$realGroup.children('.form-widget').toggleClass('form-widget');
}
});
And the twig bit:
{% block form_row -%}
{% spaceless %}
<div class="form-group{% if (not compound or force_error|default(false)) and not valid %} has-error{% endif %}">
{{ form_label(form) }}
<div class="form-widget">
{{ form_widget(form) }}
{{ form_errors(form) }}
</div>
</div>
{% endspaceless %}
{%- endblock form_row %}
Now the twig bit is the standard SF2 bootstrap form layout, I'm pretty sure i didn't alter that.
So any help getting rid of the js script and actually doing it in twig would be great, I have tried a few things but every single one of them turned out worse then what I did with js, So I'm a bit stuck.
EDIT:
What the js script does, is just removing the css classes, so the layout works. It would look flat because it would just be empty div's, but what I am after is not showing the divs in the first place. I'm trying to alter the twig script, not the css, as that is just the way we want it.
You have three options.
1.Either create each field manually:
{{ form_start(form, {'action': path(''), 'attr': {'class':'productForm'}}) }}
{{ form_errors(form) }}
<div class="form-group">
{{ form_label(form.clientTitle, 'Client 1 title:', {'label_attr': {'class': 'control-label required'}}) }}
<div class="form-widget">
{{ form_widget(form.clientTitle, { 'attr': {'class': 'form-control' }}) }}
</div>
{{ form_errors(form.clientTitle) }}
</div>
<div class="form-group">
{{ form_label(form.firstName, 'Client 1 first name:', {'label_attr': {'class': 'control-label required'}}) }}
<div class="form-widget">
{{ form_widget(form.firstName, { 'attr': {'class': 'form-control' }}) }}
</div>
{{ form_errors(form.firstName) }}
</div>
<div class="form-group">
{{ form_label(form.firstName, 'Client 1 last name:', {'label_attr': {'class': 'control-label required'}}) }}
<div class="form-widget">
{{ form_widget(form.firstName, { 'attr': {'class': 'form-control' }}) }}
</div>
{{ form_errors(form.firstName) }}
</div>
<div class="form-group form-group-submit">
<div class="">
<a id="step2_save" class="has-spinner btn btn-default btn-submit">
<span class="spinner">
<i class="fa fa-spinner fa-spin"></i>
</span>
Complete the quote
</a>
</div>
</div>
{{ form_end(change_password) }}
2.Or you could create your own form theme.
3.Or use a loop for each form:
{% for child in form.children %}
<div class="form-group">
{{ form_label(child, null, {'label_attr': {'class': 'control-label required'}}) }}
<div class="form-widget">
{{ form_widget(child, { 'attr': {'class': 'form-control' }}) }}
</div>
{{ form_errors(child) }}
</div>
{% endfor %}
It all depends on how many fields your future forms will have and how many similar forms you have.
However, using JS for such a thing is a no-no.
The easiest way is to create a custom form theme.
If you look at the current Symfony2's bootstrap one, you can see:
{% block form_row -%}
<div class="form-group{% if (not compound or force_error|default(false)) and not valid %} has-error{% endif %}">
{{- form_label(form) -}}
{{- form_widget(form) -}}
{{- form_errors(form) -}}
</div>
{%- endblock form_row %}
The "copound" stuff is actually telling you if the current element contains sub-elements (form, collection, ... basically all parent elements), and if you don't want to have that form-group
class for parents, you just need to overload this block in a custom theme.
{# AppBundle::custom_theme.html.twig #}
{% use "bootstrap_3_layout.html.twig" %}
{% block form_row -%}
<div class="{% if not compound %}form-group{% endif %}{% if (not compound or force_error|default(false)) and not valid %} has-error{% endif %}">
{{- form_label(form) -}}
{{- form_widget(form) -}}
{{- form_errors(form) -}}
</div>
{%- endblock form_row %}
If you don't want the div at all, just remove it! That's your go now.
To apply the change in your whole project, you can add this in config.yml
:
twig:
# ...
form_themes:
- 'AppBundle::custom_theme.html.twig'
Or to use it on a specific view only:
{% form_theme yourForm 'AppBundle::custom_theme.html.twig' %}
Note: yourForm
is your current form object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With