如何将实体(选择<select>)字段渲染为Twig中的字段?</select>

时间:2015-02-16 16:20:10

标签: php html symfony twig symfony-forms

  

Symfony基本上呈现entity field typechoice下拉列表 - select。但是,我正在使用的CSS框架将一种“选择”定义为ulli作为选项。 Custom Field Type文档没有提供有关此方案的帮助。

我正在使用twig和form_widget()将我的代码从表单下拉列表的手动HTML呈现转换为symfony表单的版本。但是,我想要ulli而不是select

创建下拉列表的手动方式是:

<ul class='dropdown-menu'>
    {% for locator in locators %}
        <li>
            <a href="#" data-id="{{locator.getId() }}">
                {{ locator.getName() }}
            </a>
        </li>
    {% endfor %}
</ul>

这就是我在使用symfony表单之前手动渲染下拉列表的方法。它看起来像这样:

custom css dropdown

我喜欢它。我认为它看起来很棒。现在,如果我使用Symfony表单,我可以使用它:

{{ form_start(form) }}
    {{ form_widget(form.locator) }} {# This is my locator dropdown #}
    {{ form_widget(form.target) }} {# Ignore this #}
{{ form_end(form) }}

问题是这会改为:

symfony form select dropdown

我无法在此处添加自定义CSS,因为它会呈现为select,而不是无序列表和li

如果它有帮助,这是我的表单类型:

/**
 * {@inheritDoc}
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('target')
            ->add('locator', 'entity', [
                'class'         => 'Application\Model\Entity\Locator',
                'query_builder' => function(EntityRepository $repo) {
                    return $repo->createQueryBuilder('e');
                },
                'empty_value'   => 'Locator'
            ])
            ->add('save', 'submit', ['label' => 'Save']);

    $builder->setAction($this->urlGenerator->generate('page_create_element', [
        'suiteId' => $options['suiteId'], 'pageId' => $options['pageId']
    ]))->setMethod('POST');
}

问题:有什么方法可以让上面的表单命令自动生成我的ul / li需求而不是选择,或者我必须手动渲染它而忽略symfony表单这个组件?

1 个答案:

答案 0 :(得分:2)

  

感谢上面的一些海报,有一些来自Form Theming的信息,但它还不够完整,所以我不得不在github上进行一些挖掘。

根据documentation,Symfony使用twig模板来呈现表单的相关位,并且它包含元素。这些只是{% block %}在树枝上。因此,第一步是找到在symfony代码库中呈现选择按钮的位置。

形式主题

首先,您在其自己的twig文件中创建自己的主题块,然后使用以下代码将此主题应用于表单:

{% form_theme my_form_name 'form/file_to_overridewith.html.twig %}

因此,如果我在上面的文件中覆盖了{% block form_row %},那么当我调用{{ form_row(form) }}时,它将使用我的块而不是Symfony的默认块。

重要提示:您不必覆盖所有内容。只需覆盖您想要更改的内容,如果Symfony在您的主题中找不到它,它将回归到它自己的块。

源代码

在github上,我找到了source code用于Symfony&#34;选择小部件&#34;。这有点复杂,但是如果你仔细研究并尝试一下,你会看到它的去向。

choice_widget_collapsed块中,我将选择更改为ul并将选项更改为li。这是我创建的主题文件,请注意上面描述的细微差别:

{# Symfony renders a 'choice' or 'entity' field as a select dropdown - this changes it to ul/li's for our own CSS #}

{%- block choice_widget_collapsed -%}
    {%- if required and empty_value is none and not empty_value_in_choices and not multiple -%}
        {% set required = false %}
    {%- endif -%}
    <ul {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
        {%- if preferred_choices|length > 0 -%}
            {% set options = preferred_choices %}
            {{- block('choice_widget_options') -}}
            {%- if choices|length > 0 and separator is not none -%}
                <li disabled="disabled">{{ separator }}</li>
            {%- endif -%}
        {%- endif -%}
        {%- set options = choices -%}
        {{- block('choice_widget_options') -}}
    </ul>
{%- endblock choice_widget_collapsed -%}

{%- block choice_widget_options -%}
    {% for group_label, choice in options %}
        {%- if choice is iterable -%}
            <optgroup label="{{ group_label|trans({}, translation_domain) }}">
                {% set options = choice %}
                {{- block('choice_widget_options') -}}
            </optgroup>
        {%- else -%}
            <li value="{{ choice.value }}"{% if choice is selectedchoice(value) %} selected="selected"{% endif %}><a href="#">{{ choice.label|trans({}, translation_domain) }}</a></li>
        {%- endif -%}
    {% endfor %}
{%- endblock choice_widget_options -%}

渲染

现在我可以使用以下内容呈现我的表单:

{{ form_widget(form.locator, {'attr': {'class': 'dropdown-menu'}}) }}

这使用我的主题作为选择下拉列表,其中包含ulli标记,而不是selectoption标记。一旦你知道在哪里寻找原始代码就很简单!呈现的HTML:

<ul id="elementtype_locator" name="elementtype[locator]" required="required" class="dropdown-menu">
    <li value="1"><a href="#">id</a></li>
    <li value="2"><a href="#">name</a></li>
    <li value="3"><a href="#">xpath</a></li>
</ul>

我还必须删除其中一条放置“定位器”的线路。在下拉列表的顶部,因为有四个下拉选项(包括empty_data一个)而不是三个。