简体   繁体   中英

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.

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.

Already George Irimiciuc helped you, my point is that you can use 2nd option provided in George answer, you need to focus on this part of form theme.

Symfony2 twig create form based on selected theme, if you will try to add your form theme then it will be good, others option means you are just pushing problem to other place and that's just a trick. No need to update complete form them, just add your form_row it will work, can try this

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

I used this is my project, best point is that you can send attributes from your form builder which fields and then check those under form_row, which render your form rows and can create form like you want like after check conditions -

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

and can check this under form_row like

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

and can add condition in twig.

If you have problem like your form has child form and twig form_row is showing that in odd way -

I build this project and only this till now, In that there is student entity joined with various entities so at time of form entries like Profile. I used both entity Student and Address what i did is, 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 %}

code is not exact like this but main concept is.

Hope you understand my point.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM