Symfony 表单:如何将不同的主题/小部件应用于特定的表单字段?

基于 Symfony 3.4 的表单包含多个CheckboxType字段。其中一些字段应显示为普通复选框(= 使用默认复选框小部件),而其他一些应显示为开/关开关(如 iOS UISwitche)。

因此,在相同类型的相同表单字段中 ( CheckboxType) 应该使用不同的小部件。我怎样才能做到这一点?


解决方案 1:当然我可以将自定义应用form_theme到完整的表单 ( {% form_theme form 'AppBundle:Form:myTheme.html.twig' %})。但这会影响表单中的所有复选框,而不仅仅是一个。所以这不是解决方案。


解决方案 2:一种可行的解决方案是使用其 id 将不同的小部件应用于一个特定字段:

{% block _user_registration_form_someCheckBoxRow %}
    ...
{% endblock %}

虽然此解决方案有效,但我将不得不为所有受影响的表单中的所有受影响的字段创建/覆盖相同的块。这非常麻烦,因此不是一个好的解决方案。


解决方案 3:另一个可行的解决方案是创建一个自定义项,FormType供应显示为开关的复选框使用。此表单类型将扩展CheckboxType并且除了重写blockPrefix.

虽然这非常接近于一个好的解决方案,但有一个主要缺点:假设复选框开关有不同的主题/小部件。一个标签在顶部,一个标签在开关旁边,等等。这些样式中的每一个不仅需要自己的小部件,还需要自己的表单类型,需要在 等中注册。这当然可以FormPass.php工作但也相当麻烦且容易出错。

所以,这将是解决方案,但不是nice一个。


难道没有更好的办法吗?我正在寻找类似的东西{{ form_row(form.someCheckbox, 'someWidget') }}。每个主题只有一个额外的文件,并且可以准确地分辨出哪个字段使用哪个主题。不需要额外的类、配置等。我以这种方式一无所获。

使用虚拟表单类型真的是最好的解决方案吗?


慕桂英546537
浏览 128回答 2
2回答

一只萌萌小番薯

以下内容适用于 Symfony 5.0.x(尽管 3.4 不需要进行重大更改,可能只需要一些额外的配置):要抽象主题处理,请定义您自己的复选框类型,如下(例如):<?phpdeclare(strict_types=1);namespace App\Form\Type;use Symfony\Component\Form\AbstractType;use Symfony\Component\Form\Extension\Core\Type\CheckboxType;use Symfony\Component\OptionsResolver\Options;use Symfony\Component\OptionsResolver\OptionsResolver;class ThemedCheckboxType extends AbstractType{    /**     * @param OptionsResolver $resolver     */    public function configureOptions(OptionsResolver $resolver): void    {        $resolver            ->setDefaults([                'theme' => 'default',                'block_prefix' => static function (Options $options): ?string {                    return [                        'default' => null,                        'theme-a' => 'theme_a_checkbox',                        'theme-b' => 'theme_b_checkbox',                    ][$options['theme']];                },            ])            ->setAllowedValues('theme', ['default', 'theme-a', 'theme-b']);    }    /**     * @inheritDoc     */    public function getParent(): string    {        return CheckboxType::class;    }}然后在需要的地方简单地使用它,例如:$builder->add('test_a1', ThemedCheckboxType::class, [    'theme' => 'theme-a', // or others]);这样,您可以注入自己的表单主题,在需要时直接操作复选框,例如{% block theme_a_checkbox_widget %}    <em>Theme-A</em>    {{ block('checkbox_widget') }}{% endblock %}{% block theme_b_checkbox_widget %}    <em>Theme-B</em>    {{ block('checkbox_widget') }}{% endblock %}如果您不想使用额外的表单类型,可以使用自定义表单扩展来为默认复选框类型添加选项来实现同样的效果。请参阅: https: //symfony.com/doc/current/form/create_form_type_extension.html例如:<?phpdeclare(strict_types=1);namespace App\Form\Extension;use Symfony\Component\Form\AbstractTypeExtension;use Symfony\Component\Form\Extension\Core\Type\CheckboxType;use Symfony\Component\OptionsResolver\Options;use Symfony\Component\OptionsResolver\OptionsResolver;class CheckboxTypeExtension extends AbstractTypeExtension{    /**     * @inheritDoc     */    public static function getExtendedTypes(): iterable    {        return [CheckboxType::class];    }    /**     * @inheritDoc     */    public function configureOptions(OptionsResolver $resolver): void    {        $resolver            ->setDefaults([                'theme' => 'default',                'block_prefix' => static function (Options $options): ?string {                    return [                        'default' => null,                        'theme-a' => 'theme_a_checkbox',                        'theme-b' => 'theme_b_checkbox',                    ][$options['theme']];                },            ])            ->setAllowedValues('theme', ['default', 'theme-a', 'theme-b']);    }}这允许:$builder->add('test_a1', CheckboxType::class, [    'theme' => 'theme-a',]);

暮色呼如

您可以将主题应用于单个复选框:{% form_theme form.my_special_checkbox 'Form/Theme/special_checkbox.html.twig' %}或者,如果您不需要单独的主题(单个用例),您可以在当前 Twig 文件中编写块:{% block _my_checkbox_widget_block %}     {# the theme #}     {% endblock %} {% form_theme form.my_special_checkbox _self %}我会使用自定义块名称创建自定义复选框组件并将其放入全局表单主题中,以便我可以在整个应用程序中重用它。
打开App,查看更多内容
随时随地看视频慕课网APP