Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 810
DarkMukke Avatar asked Oct 02 '15 08:10

DarkMukke


2 Answers

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.

like image 162
George Irimiciuc Avatar answered Nov 14 '22 12:11

George Irimiciuc


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.

like image 2
Alain Tiemblo Avatar answered Nov 14 '22 13:11

Alain Tiemblo