Customize the rendering of a choice/entity field in Symfony2

12,657

Solution 1

1. Manually rendering. Better if is a individual form for field and not repeated somethere as it requires less time to work.

A) Get name of field you can with form.service.vars.full_name

B) List of choices - form.service.vars.choices. Its an array of ChoiceView, to get entity simply access public data property.

{% for choice in form.service.vars.choices %}
    {% set service_entity = choice.data %}
{% endfor %}

2. Via overriding templates. IF you like to brute-force pick up the name of the blocks which must be overriden.

A) You can only override widget, label and errors blocks as documentation said. You can specify block by widget name(documentation). Something like

{% block _form_service_widget %}
    {% if expanded %}
        {{ block('choice_widget_expanded') }}
    {% else %}
        {{ block('my_service_widget') }}
    {% endif %}
{% endblock %}

{% block my_service_widget %}
{% spaceless %}
    <select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
        {% if empty_value is not none %}
            <option value="">{{ empty_value|trans({}, translation_domain) }}</option>
        {% endif %}
        {% set options = choices %}
        {{ block('my_service_options') }}
    </select>
{% endspaceless %}
{% endblock my_service_widget %}

{% block my_service_options %}
{% spaceless %}
    {% for group_label, choice in options %}
        {# here you can access choice #}
        <option value="{{ choice.value }}"{% if choice is selectedchoice(value) %} selected="selected"{% endif %}>{{ choice.label|trans({}, translation_domain) }}</option>
    {% endfor %}
{% endspaceless %}
{% endblock my_service_options %}

Solution 2

You can use the choice_attr option in the form builder:

$builder->add('myField', ChoiceType:class, [
        ....
        'choice_attr' => function($val, $key, $index) {
            return ['data' => '...', 'class' => '', ... etc ];
        },
        ....
]);

This will apply attributes to each option, checkbox, radio in your choice (depending on your expanded and multiple option choices)

Share:
12,657
Levente Pánczél
Author by

Levente Pánczél

Updated on June 15, 2022

Comments

  • Levente Pánczél
    Levente Pánczél almost 2 years

    I would like a <select> element to be rendered with additional data on its <option>s. For the sake of example, I'd like to have a service-selector (non-multiple entity-field) that resets another inputs value upon selection change. I'm not interested in using JS data-structures, I need to have the rendered field to look as follows:

    <select name="...">
        <option value="1" data-price="90">Service 1</option>
        <option value="2" data-price="40">Service 2</option>
    </select>
    

    I would take two different solutions and would be glad to see the answer to both of them.

    1. I'd render the field manually in Twig by starting to assemble the above HTML code by using the form variable I passed to the twig. I have two problems solving this. A) I can't find a safe way to tell what the filed should be named, i.e. how do I get the name attribute that Symfony expects by using the variable form.service (service is the name of the field in the FormType). [Please spare me tricks that concatenate some values based on observing how fields are currently named by Symfony; one should rely on interfaces and not on reverse engineering.] B) I don't know how to access the list of choices, i.e. the array assembled by the entity field's query_builder option. [Since I'm looking for a general solution, I'm not willing to duplicate these items over to a twig-parameter in the controller -- just to avoid such suggestions.]
    2. I'd override the rendering of the relevant field blocks, as suggested in the form styling chapter of the cookbook, but there are three problems with that. A) I cannot find out which blocks should be overridden (and so I don't find samples). B) I would pass parameter from the form builder to the block to let it know what extra data- attributes are to be rendered, but I don't know how to do this. And finally C) in those cases where I don't need to deviate from standard rendering (e.g. when the field is multiple) I don't know how to fallback to the default rendering.

    So these are actually 5 questions (1A,1B,2A,2B,2C) but I thought them to be more useful to others answered together, since they all address what I think is an undocumented spot regarding choice field rendering.

  • Rodolfo Velasco
    Rodolfo Velasco over 9 years
    How can you access to the selected value from a select type field with twig?
  • marsbear
    marsbear about 8 years
    By using this {% if choice.data in value %} selected="selected"{% endif %}