php - 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') }}
。每个主题只会有一个额外的文件,并且可以准确地分辨出哪个字段使用哪个主题。不需要额外的类、配置等。我没有以这种方式找到任何东西。
使用虚拟表单类型真的是最好的解决方案吗?
解决方案
参考我上面的最后一条评论,以下适用于 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.com/doc/current/form/create_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',
]);
推荐阅读
- rider - 发布单文件 Rider IDE
- javascript - 一个为数字类型输入动态生成 step 属性的衬垫?
- r - 使用 dtplyr 时,将函数输入中的列用于 group_by 变量
- swift5 - 如何使用 BGTaskScheduler 在后台快速调用 API?
- object - 将 fxml 文件视为边界窗格的中心疼痛中的对象
- laravel - 从多态表中获取记录
- sql - 这是我需要的正确 SQL 吗?[JDE、DB2]
- mysql - MySQL 包含一个数字的字母数字异构字符串列,按该数字排序
- yaml - 在 Swagger/YAML 文件中使用多个对象
- docker - Elasticsearch/docker数据节点关机后无法重新连接