18

I want get form field type and set class fot field type

i try:

{# Form field row #}
{% block form_row %}
{% spaceless %}
  <div class="field-group{% if errors|length > 0%} error{%endif%}" id="fc-{{ id }}">
    {{ form_label(form, label|default(null)) }}
    <div class="field-item {{ type }}">
      {{ form_widget(form) }}
      {% if errors|length > 0 %}
        <div class="errors">{{ form_errors(form) }}</div>
      {% endif %}
    </div>
  </div>
{% endspaceless %}
{% endblock %}

But {{ type }} not working.

ZhukV
  • 2,892
  • 6
  • 25
  • 36
  • 1
    Because you've to set the type before using it. Try adding {% set type = type|default(your_type) %} where your_type should be retrieved from "form.vars.types" to display whatever you want as a class for your fields. – Ahmed Siouani Nov 02 '12 at 14:54
  • Not, this is bad idea. I want get field type and add this type as class to "div" conainer. Example: is field as "file" type. Result:
    {fieldWidget}
    Thank!
    – ZhukV Nov 02 '12 at 18:57

5 Answers5

25

The answer from MatsRietdijk is right, but as of Symfony 2.3 the index of the type seems to have changed from 2 to 1. As a result, {{ form.vars.block_prefixes.1 }} will return checkbox, date, choice, etc.

You can use it to add a class to the form row when making application-wide customizations:

{% block form_row %}
    <div class="form_row {{ form.vars.block_prefixes.1 }}">
        {{ form_label(form) }}
        {{ form_widget(form) }}
        {{ form_errors(form) }}
    </div>
{% endblock form_row %}

Then you can apply CSS rules:

div.form_row.text {color:Red;}

Twitter Bootstrap

If you use Twitter bootstrap, you may have problems since the .checkbox class exists in bootstrap. I suggest to use a prefix for Symfony forms rows:

{% block form_row %}
    <div class="form_row symfony_{{ form.vars.block_prefixes.1 }}">
        {{ form_label(form) }}
        {{ form_widget(form) }}
        {{ form_errors(form) }}
    </div>
{% endblock form_row %}

The rules in the CSS files will be different:

div.form_row.symfony_text {color:Red;}

Update

Twitter bootstrap form theme is now included in Symfony 2.6.

A.L
  • 10,259
  • 10
  • 67
  • 98
  • 2
    NOTE: on nested/included forms it returns the name of the entity (because this is actually the custom field type name). For example, on a regular text field: 0=>form, 1=>text, 3=>_view_version_title On a ckeditor field: 0=>form, 1=>text, 2=>textarea, 3=>ckeditor, 4=>_view_version_content_content But on a nested form: 0=>form, 1=>viewVersion, 2=>_view_version – Chadwick Meyer Jun 12 '14 at 22:36
19

You can get the field type by using this:

{{ form.FIELD_NAME.vars.block_prefixes.2 }}

So if you got a field called message in your form use this:

{{ form.message.vars.block_prefixes.2 }}

For nested form field types use this:

{{ form.NESTED_FORM_NAME.FIELD_NAME.vars.block_prefixes.2 }}

EDIT :

To overwrite the basic form blocks do this in your template file:

....
{% form_theme form _self %}
{% block widget_attributes %}
{% spaceless %}
    id="{{ id }}" name="{{ full_name }}"{% if read_only %} readonly="readonly"{% endif %}{% if disabled %} disabled="disabled"{% endif %}{% if required %} required="required"{% endif %}{% if max_length %} maxlength="{{ max_length }}"{% endif %}{% if pattern %} pattern="{{ pattern }}"{% endif %}
    {% if not attr.class is defined %}
        class="{{ type|default('text') }}"
    {% endif %}
    {% for attrname, attrvalue in attr %}{% if attrname in ['placeholder', 'title'] %}{{ attrname }}="{{ attrvalue|trans({}, translation_domain) }}" {% elseif attrname == 'class' %}{{ attrname }}="{{ type|default('text') }} {{ attrvalue }}"{% else %}{{ attrname }}="{{ attrvalue }}" {% endif %}{% endfor %}
{% endspaceless %}
{% endblock widget_attributes %}
{% block content %}
    ....
{% endblock %}

OR to get beter types:

....
{% form_theme form _self %}
{% block widget_attributes %}
{% spaceless %}
    id="{{ id }}" name="{{ full_name }}"{% if read_only %} readonly="readonly"{% endif %}{% if disabled %} disabled="disabled"{% endif %}{% if required %} required="required"{% endif %}{% if max_length %} maxlength="{{ max_length }}"{% endif %}{% if pattern %} pattern="{{ pattern }}"{% endif %}
    {% if not attr.class is defined %}
        class="{{ form.vars.block_prefixes.2 }}"
    {% endif %}
    {% for attrname, attrvalue in attr %}{% if attrname in ['placeholder', 'title'] %}{{ attrname }}="{{ attrvalue|trans({}, translation_domain) }}" {% elseif attrname == 'class' %}{{ attrname }}="{{ form.vars.block_prefixes.2 }} {{ attrvalue }}"{% else %}{{ attrname }}="{{ attrvalue }}" {% endif %}{% endfor %}
{% endspaceless %}
{% endblock widget_attributes %}
{% block content %}
    ....
{% endblock %}
Mats Rietdijk
  • 2,576
  • 3
  • 20
  • 25
  • 1
    This is bad idea ( There must be some variable that indicates the type of the field! – ZhukV Nov 03 '12 at 18:52
  • 1
    I have been trying to find that too, after a lot of var_dumps, foreach loops and a couple of hours spend reading classes this is what I found – Mats Rietdijk Nov 03 '12 at 18:56
  • 1
    Also the block_prefixes are variables of the field and they contain the field type of the `input` block – Mats Rietdijk Nov 03 '12 at 18:59
  • Thank, but each form_row must be a variable that indicate type of field! I want get this field type and add type as class to field container. – ZhukV Nov 03 '12 at 19:00
  • Thats why my answer states that you need to access the vars of a row by doing `form.FIELD_NAME` the FIELD_NAME is the same as the row name, I will edit my answer. – Mats Rietdijk Nov 03 '12 at 19:04
  • i have form theme: {% block form_row %}
    .....
    {% endblock %}
    – ZhukV Nov 03 '12 at 19:06
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/19026/discussion-between-zhukv-and-matsrietdijk) – ZhukV Nov 03 '12 at 19:09
  • that numeric index variates depending on the type and most of the time 2 indicates the actual field name, not the guessed formType examples folow, showing output of `{{dump(form.vars.block_prefixes)}}` --> `0 =>string'form' 1 =>string'text' 2 =>string'textarea' 3 =>string'_lifeCycle_note'` and `0 =>string'form' 1 =>string'checkbox' 2 =>string'_lifeCycle_ready'`. As I needed to know if dealing with checkboxes (to render label AFTER input) I used `{% if form.vars.block_prefixes.1 == 'checkbox' %}` – juanmf Jun 10 '14 at 23:05
  • If I knew the field name, then I would know the field type :) So... +1 for effort, but this doesn't help me ;( But the answer below by A.L. works for me: `{{ form.vars.block_prefixes.1 }} – Chadwick Meyer Jun 12 '14 at 22:39
2

block_prefixes is used to generate block names to display field (cf FormRenderer::searchAndRenderBlock method). The most specific existing block in template (generally form_div_layout.html.twig file) will be displayed.

So, the last item of block_prefixes is the id of your input, to allow you to override block for a specific field.

Previous item will be the item you need.

You can use this one : $form->vars.block_prefixes[$form->vars.block_prefixes|count -2] in smarty syntax.

Rey0bs
  • 1,192
  • 12
  • 19
  • 1
    ```formName.vars.block_prefixes[formName.vars.block_prefixes|length -2]``` in twig – VMC Apr 21 '18 at 09:30
1

To avoid hardcoding the array index (1 or 2 depending on Symfony version), i've used the following:

{{ form.vars.block_prefixes | slice(-2,1) | first }}
umarbahadoor
  • 11
  • 1
  • 1
-1

Use

{{ form.name.vars.original_type }}

E.g. from one of my templates

{% if myform.fieldname.vars.original_type == 'choice' %}
    <hr>
    {{ form_label(myform.fieldname) }}
    <p>Select a ...</p>
    {{ form_widget(myform.fieldname) }}
{% elseif myform.fieldname.vars.original_type == 'hidden' %}
    {{ form_row(myform.fieldname) }}
{% endif %}
Ross
  • 472
  • 1
  • 4
  • 11