如何将实体(选择< select>)字段呈现为< ul>在树枝的领域? [英] How can I render an entity (choice <select>) field as a <ul> field in Twig?

查看:120
本文介绍了如何将实体(选择< select>)字段呈现为< ul>在树枝的领域?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


Symfony呈现,但它不够完美,所以我不得不在github上进行一些挖掘。


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



表单主题



首先,你在它自己的树枝文件中创建自己的主题块,然后用下面的代码将这个主题应用到你的表单中:

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

所以如果我重写 {%block form_row%} ,然后当我调用 {{form_row(form)}} 时,它会使用我的区块而不是Symfony的默认区块。



重要提示:您不必重写所有内容。只要覆盖你想改变的东西,Symfony就会回到它自己的区块,如果它没有在你的主题中找到它的话。



源代码



在github上,我找到了源代码 Symfony的选择小部件。这有点复杂,但如果你仔细观察并试验一下,你就会发现它在哪里。



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

  {#Symfony呈现'选择'或'实体'字段作为选择下拉菜单 - 将其更改为我们自己的CSS的ul / li#} 

{% - block choice_widget_collapsed - %}
{% - 如果需要,empty_value是none且不是empty_value_in_choices而不是多个 - %}
{%set required = false%}
{% - endif - %}
    {% - if preferred_choices | length> 0 - %}
    {%set options = preferred_choices%}
    {{ - block('choice_widget_options') - }}
    {% - if choices | length> 0并且分隔符不是无 - %}
  • {% - endif - %}
    {% - endif - %}
    {% - set options = choices - %}
    {{ - block('choice_widget_options') - }}
    < / ul>
    {% - endblock choice_widget_collapsed - %}

    {% - block choice_widget_options - %}
    {%为group_label,选项为%}
    {% - if选择是可迭代的 - %}
    {%set options = choice%}
    {{ - block('choice_widget_options') - }}
    < / optgroup>
    {% - else - %}
  • {% - endif - %}
    {%endfor%}
    {% - endblock choice_widget_options - %}



渲染



现在我可以使用以下方式呈现我的表单:

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

这将我的主题用于包含 ul li的选择下拉菜单标记而不是选择选项 ones。很简单,一旦你知道在哪里寻找原始代码!呈现的HTML:

 < ul id =elementtype_locatorname =elementtype [locator]required =requiredclass = 下拉菜单 > 
< li value =1>< a href =#> id< / a>< / li>
< li value =2>< a href =#>名称< / a>< / li>
< li value =3>< a href =#> xpath< / a>< / li>
< / ul>

我也不得不删除将'Locator'放在下拉列表顶部的其中一行有四个下拉选项(包括empty_data),而不是三个。


Symfony renders an entity field type like a choice dropdown - a select, basically. However, the CSS framework that I'm using defines a sort of 'select' as a ul and li as the options. The Custom Field Type documentation gives no help on this scenario.

I'm converting my code from manual HTML rendering of the form dropdown to symfony form's version using twig and form_widget(). However, I want a ul and li instead of a select.

The manual way of creating my dropdown is:

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

That's how I would render my dropdown manually before using symfony forms. It looks like this:

I like it. I think it looks awesome. Now, if I'm using Symfony forms, I can just use this instead:

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

The problem is that this renders this instead:

I can't add my custom CSS here because this is rendered as a select instead of an unordered list and lis.

In case it may help, here's my form type being built:

/**
 * {@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');
}

The Question: Is there any way I can have the form commands above auto-generate my ul / li requirement instead of selects, or do I have to render this manually instead and ignore the symfony forms component for this?

解决方案

Thanks to some of the posters above, there was some information from Form Theming, but it wasn't exactly enough to go along with so I had to do a little bit of digging on github.

According to the documentation, Symfony uses twig templates to render the relevant bits of a form and it's containing elements. These are just {% block %}s in twig. So the first step was to find where a select button is rendered within the symfony codebase.

Form Theming

Firstly, you create your own theme block in it's own twig file and you apply this theme to your form with the following code:

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

So if I had overridden {% block form_row %} in the file above, then when I called {{ form_row(form) }} it would use my block instead of Symfony's default block.

Important: You don't have to override everything. Just override the things you want to change and Symfony will fall back to it's own block if it doesn't find one in your theme.

The Sourcecode

On github I found the source code for Symfony's "choice widget". It's a little complex but if you follow it through and experiment a little bit you'll see where it goes.

Within the choice_widget_collapsed block, I changed the select to uls and options to lis. Here's the theme file I created, note the minor differences described above:

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

Rendering

Now I can render my form with the following:

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

This uses my theme for the choice dropdown which contains ul and li tags instead of select and option ones. Pretty simple once you know where to look for the original code! The rendered 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>

I also had to remove one of the lines that put 'Locator' at the top of the dropdown as there were four dropdown choices (including the empty_data one) instead of three.

这篇关于如何将实体(选择&lt; select&gt;)字段呈现为&lt; ul&gt;在树枝的领域?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆