Symfony表格。如何在特定的表单字段中应用不同的主题小工具?

问题描述 投票:0回答:1

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

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


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


解决方案2: 一个可行的解决方案是使用不同的widget来应用于一个特定的字段。

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

虽然这个解决方案可行,但我必须为所有受影响的表单中所有受影响的字段创建覆盖相同的块。这很麻烦,因此不是一个好的解决方案。


解决方案3: 另一个可行的解决方案是创建一个自定义的... FormType 用来作为开关显示的复选框。这种表格类型将扩展 CheckboxType 而什么也不做,只是覆盖了 blockPrefix.

虽然这很接近一个好的解决方案,但有一个主要的缺点。假设复选框开关有不同的主题小工具 一个标签在上面,一个标签在开关旁边,等等。每一种风格不仅需要自己的widget,而且还需要自己的表单类型,这些都需要在下面的表单中注册。FormPass.php,等等。这样当然可以,但也相当麻烦,容易出错。

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


难道没有更好的方法吗?我在寻找类似 {{ form_row(form.someCheckbox, 'someWidget') }}. 每个主题只会有一个额外的文件,可以精确的知道哪个字段使用了哪个主题。不需要额外的类,配置等。我发现这种方式没有什么用。

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

php symfony symfony-forms
1个回答
1
投票

参考我上面的评论,以下内容在Symfony 5.0.x中可以使用(尽管在3.4中不需要做任何重大改变,可能只是一些额外的配置)。

为了抽象主题处理,定义你自己的复选框类型,如下所示(例如)。

<?php
declare(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.comdoccurrentformcreate_form_type_extension.html。

例如:

<?php
declare(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',
]);

0
投票

你可以申请 题材 到一个单独的复选框。

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

我会用自定义的块名创建自定义的复选框组件,然后把它放在一个全局的主题里,这样我就可以在整个应用程序中重复使用它。

© www.soinside.com 2019 - 2024. All rights reserved.