使用多个单词名称创建自定义Symfony FormType小部件

时间:2015-10-09 00:33:21

标签: forms symfony

Symfony可让您轻松customize, extend, or create your own form type widgets。如果要将新表单类型命名为“foo”,则此方法很有用。但是,如果您想使用两个字命名自定义类型,例如fooBar,那么您将如何命名PHP formType,服务和Twig?有很多symfony核心表单类型的例子,它们是由下划线分隔的多个单词,例如: collection_item_widget。但这对自定义表单类型不起作用。

因此,如果您想创建一个名为fooBarType的新表单类型,您将创建一个名为fooBarType.php的控制器

class FooBarType extends AbstractType {
    public function getName() {
        return 'fooBar';
    }

    public function getParent() {
        return 'form';
    }
}

将此项设为服务(可选):

cms.form.type.foo_bar:
    class: Cms\FooBundle\Form\Type\FooBar
    tags:
        - { name: form.type, alias: fooBar }

然后自定义fields.html.twig并为名为foo_bar_widgetfoobar_widgetfooBar_widget创建一个块(这些都不起作用):

{% block foo_bar_widget %}
    {{ block('entity_widget') }}
{% endblock %}

注意:如果它位于不同的位置,您还必须在config.yml中注册

twig:
    form:
        resources:
            - 'CmsFooBundle:Form:fields.html.twig'

然后在表单构建器中使用该字段,例如

$builder->add('myField', 'fooBar');

一切都在上面工作,除了fields.html.twig中的自定义块不呈现,除非我将所有名称更改为像'foo'这样简单的名称。

¿Por Que?

2 个答案:

答案 0 :(得分:2)

我的例子的问题在于从服务定义开始的camelCase的不一致性,以及树枝模板中的问题。

从技术上讲,根据规范,服务应该是小写和下划线,例如cms.form.type.foo_bar。并且枝条小部件定义也是下划线,例如collection_item_widget。因此,尽管camelCase和下划线工作(如果你在widget中是一致的,formType控制器的getName(),以及$ formBuilder-> add()函数),它应该总是下划线。

现在这对我有用:

控制器

class FooBarType extends AbstractType {
    public function getName() {
        return 'foo_bar';
    }

    public function getParent() {
        return 'form';
    }
}

服务定义

cms.form.type.foo_bar:
    class: Cms\FooBundle\Form\Type\FooBar
    tags:
        - { name: form.type, alias: foo_bar }

表单构建器中的用法

$builder->add('myField', 'foo_bar');

fields.html.twig fields.html.twig可以定义为camelCase(以匹配别名)。但显然没有block('entity_widget')这样的事情。我认为实体只是选择小部件的扩展。所以我的自定义小部件正在加载,但没有选择,因为该块不正确。如果我将其更改为choice_widget

,则可以使用它
{% block foo_bar_widget %}
    <!-- some customizations -->
    {{ block('choice_widget') }}
{% endblock %}

答案 1 :(得分:1)

前面的说明:如果您没有任何参数或其他服务需要注入该类型,则不必将表单类型定义为服务。您始终可以通过以下方式直接在表单构建器中调用表单类型:

$builder
    ->add('foo_bar_field', new FooBarType());

无论如何,我只是使用documentation中的性别类型示例进行了快速测试,它对我来说很好。

这些是我使用的设置:

输入类 Jahller \ TestBundle \ Form \ Type \ GenderDoType.php

namespace Jahller\TestBundle\Form\Type;

// ...

class GenderDoType extends AbstractType
{
    // ...

    public function getParent()
    {
        return 'choice';
    }

    public function getName()
    {
        return 'genderDo';
    }
}

服务定义 Jahller / TestBundle / Resources / config / services.yml

jahller.form.type.gender:
        class: Jahller\TestBundle\Form\Type\GenderDoType
        tags:
            - { name: form.type, alias: genderDo }

键入树枝模板 Jahller / TestBundle / Resources / views / Form / fields.html.twig

{% block genderDo_widget %}
    {% spaceless %}
        {% if expanded %}
            <ul {{ block('widget_container_attributes') }}>
                {% for child in form %}
                    <li>
                        {{ form_widget(child) }}
                        {{ form_label(child) }}
                    </li>
                {% endfor %}
            </ul>
        {% else %}
            {# just let the choice widget render the select tag #}
            {{ block('choice_widget') }}
        {% endif %}
    {% endspaceless %}
{% endblock %}

类型包含 Jahller \ TestBundle \ Form \ TestType.php

的表单类
namespace Jahller\TestBundle\Form;

// ...

class TestType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('gender_code', 'genderDo', array(
                'placeholder' => 'Choose a gender',
            ));
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        // ...   
    }

    public function getName()
    {
        return 'test';
    }
}

渲染类型:

enter image description here

也许你可以在我的代码中找到你做的不同的事情。