在symfony 2.7之前,attr字段的choice值仅应用于字段本身,即呈现的元素。我用这个来将类应用到这个元素中来设计它的样式。
在symfony 2.7中,这种行为被改变了。现在,元素的所有子元素也得到相同的属性(commit of the change)和类。
对于一些澄清,请使用以下代码:<?php echo $view['form']->widget($form['myField'], ['attr' => ['class' => "text ui-widget-content ui-corner-all"]]); ?>
这是symfony<=2.6的输出:
Option 1
Option 2
这是symfony>=2.7的输出:
Option 1
Option 2
我应用的类不适合元素,因为它们为实际字段定义边框等。注意,这些是由jquery ui定义的类,所以我不能轻易地更改它们的定义。
在将这些类应用于元素的同时,避免将其应用于choice字段的所有元素的最简单方法是什么?
最佳答案
感谢@user2268997对choice_attr的评论,我找到了相关的博客文章New in Symfony 2.7: Choice form type refactorization,其中详细介绍了(截至目前为止)使用choice_attr选项的情况。
似乎symfony在呈现字段时将choice_attr中的属性与attr中的属性合并。这意味着我们需要覆盖class中的choice_attr属性。
我尝试在定义attr的代码旁边执行此操作,但没有成功。似乎需要在表单类型定义中执行此操作。以下是添加choice_attr选项后的表单摘录:namespace MyBundle\Form;
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('roles',
'entity',
[
'class' => 'MyBundle:Role',
'choice_label' => 'name',
'multiple' => true,
'choice_attr' => function () { return ["class" => ""]; }
]);
}
结果正如我所希望的。我可能还会将其重构为我自己的自定义表单类型,这样就不需要在我的包中重复它了。
我现在决定用上面描述的期望行为创建一个自定义choice类型,并在我的应用程序中使用它。
这是我选择的类型:
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ChoiceNoOptAttrType extends ChoiceType {
public function configureOptions(OptionsResolver $resolver) {
parent::configureOptions($resolver);
$resolver->setDefault("choice_attr", function () { return ["class" => ""]; });
}
}
我不想重构所有现有的表单来使用这种新类型,所以我选择用我的选择类型替换symfony提供的选择类型。这可以通过修改choice表单类型的服务配置来实现。为此,我为我的包创建了一个编译器传递。
进一步阅读:Creating a Compiler Pass
namespace MyBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class MyCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition("form.type.choice");
$definition->setClass('MyBundle\Form\ChoiceNoOptAttrType');
}
}
现在要做的就是在包中注册编译器传递。
进一步阅读:How to Work with Compiler Passes in Bundles
namespace MyBundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use MyBundle\DependencyInjection\Compiler\MyCompilerPass;
class MyBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new MyCompilerPass());
}
}
就这样。现在,我所有的choice字段都在使用我的自定义类,该类确保attr中设置的css类不会传播到我的元素。