自定义Symfony2中选择/实体字段的呈现


Customize the rendering of a choice/entity field in Symfony2

我希望<select>元素在其<option> s上呈现额外的数据。为了便于示例,我希望有一个服务选择器(非多个实体字段),它在选择更改时重置另一个输入值。我对使用JS数据结构不感兴趣,我需要渲染字段如下所示:

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

我会采取两种不同的解决方案,并且很高兴看到这两种解决方案的答案。

  1. 我将在Twig中手动渲染该字段,通过使用我传递给Twig的form变量开始组装上述HTML代码。解决这个问题有两个问题。A)我找不到一个安全的方法来告诉该字段应该被命名,即我如何通过使用变量form.service获得Symfony期望的name属性(服务是FormType中字段的名称)。请给我一些基于观察字段当前如何由Symfony命名的方法来连接一些值的技巧;应该依赖于接口,而不是逆向工程。[strong>B)我不知道如何访问选择列表,即由entity字段的query_builder选项组装的数组。[因为我正在寻找一个通用的解决方案,所以我不愿意将这些项目复制到控制器中的小参数中—-只是为了避免这样的建议。]
  2. 我将重写相关字段块的呈现,就像在烹饪书的表单样式章节中建议的那样,但是这样做有三个问题。A)我无法找出哪些块应该被覆盖(所以我找不到样本)。B)我会从表单构建器传递参数到块,让它知道什么额外的data-属性被渲染,但我不知道如何做到这一点。最后C)在那些情况下,我不需要偏离标准渲染(例如,当字段是多个)我不知道如何回退到默认渲染。

所以这些实际上是5个问题(1A,1B,2A,2B,2C),但我认为它们对其他人一起回答更有用,因为它们都解决了我认为是关于选择字段渲染的未记录点。

1。手动渲染。最好是一个单独的表单字段,而不是重复的地方,因为它需要更少的时间来工作。

A)获取form.service.vars.full_name字段的名称

B)选项列表- form.service.vars.choices。这是一个ChoiceView的数组,获取实体只需访问公共data属性。

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

2。通过覆盖模板。如果你喜欢暴力破解,挑选那些必须被覆盖的块的名字。

A)如文档所述,您只能覆盖widget, labelerrors块。您可以通过部件名称(文档)指定块。比如

{% 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 %}

您可以在表单生成器中使用choice_attr选项:

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

这将应用属性到每个option, checkbox, radio在您的选择(取决于您的expandedmultiple选项的选择)