Reduce the layout of form groups in Twig with Symfony2 (.7)

I am trying to get rid of duplicate twig layouts for symfony2 forms Currently my layout looks something like this:

<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 the way I want it to display, but that is said to be dirty. So I was wondering if anyone could help me modify my twig file to only show css class classes and widget classes for children and not for parents.

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 a branch 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 branch bit is the standard SF2 bootstrap format, I'm sure I haven't changed it.

So any help getting rid of the js script and actually doing it in twig would be great, I tried a few things, but each of them turned out to be worse than what I did with js. So I'm a little stuck.

EDIT:

What the js script does is simply remove the css classes, so the layout works. It would look flat because it would just be an empty div, but what I am behind it does not show divs in the first place. I am trying to change the script branch, not css, as this is the way we want it.

+6
source share
3 answers

You have three options.

1. 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 can create your own theme.

3. 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 the number of fields in your future forms and the number of similar forms.

However, using JS for such a thing is no no.

+2
source

The easiest way is to create a custom form theme.

If you look in the current Symfony2 boot file , 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 β€œconsocial” stuff actually tells you if the current element contains subelements (form, collection, ... basically all parent elements), and if you don't want to have this 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 need a div, just delete it! What do you want now.


To apply the changes throughout the project, you can add this to config.yml :

 twig: # ... form_themes: - 'AppBundle::custom_theme.html.twig' 

Or use it only for a specific view:

 {% form_theme yourForm 'AppBundle::custom_theme.html.twig' %} 

Note: yourForm is your current form object.

+2
source

George Irimichuk has already helped you, I want to say that you can use the second option provided in George’s answer, you need to focus on this part of the form topic.

Symfony2 twig create a form based on the selected theme, if you try to add a theme of your form, then it will be fine, other options mean that you just click the problem to another place and this is just a trick. No need to update their full form, just add the form form_row, it will work, can try it.

http://symfony.com/doc/current/cookbook/form/form_form_customization.html#customizing-the-form-row

I used this my project, it’s best that you can send attributes from your form builder and then check them in form_row, which displays your lines in the form and can create the form as you want, as after the validation conditions -

 attr => array( 'parent_class' => false) 

and you can check this in form_row as

 if( form.vars.attr.parent_class is defined ) 

and can add a condition to the twig.

If you have a problem, since your form has a child form, and twig form_row shows this in an odd way -

I am creating this project and only this so far. It has a student entity combined with various objects, so during form entries such as Profile. I used both Student and Address objects, which I did, I just checked this.

  {% if ( not form.children ) or ( form.vars.expanded is defined and form.vars.expanded ) %} <div class="{{ form.vars.attr['parent-div-class'] is defined ? form.vars.attr['parent-div-class'] : 'col-sm-12'}}"> <div class="form-group"> {{ form_label(form) }} {{ form_widget(form) }} {% if form_errors(form) %} {{ form_errors(form) }} {% endif %} </div> </div> {% else %} <div class="clear-both"></div> {{ form_label(form) }} {{ form_widget(form) }} {% endif %} 

the code is not like this, but a basic concept.

I hope you understand my point.

+1
source

All Articles