Благодаря комментарию @user2268997 о choice_attr
я нашел соответствующую запись в блоге Новое в Symfony 2.7: Рефакторинг типа формы выбора , в котором подробно описывается использование (на данный момент недокументированного) параметра 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
. Для этого я создал проход компилятора для своего пакета.
Дополнительная литература: Создание прохода компилятора
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');
}
}
Теперь осталось только зарегистрировать проход компилятора в бандле.
Дополнительная литература: Как работать с проходами компилятора в пакетах
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
используют мой пользовательский класс, который гарантирует, что класс CSS, установленный в attr
, не распространяется на мои элементы <option>
.
person
Chris
schedule
17.08.2015
'choice_attr'
. - person user2268997   schedule 17.08.2015$choice
, который является экземпляромChoiceView
, который создаетсяDefaultChoiceListFactory
, а параметрchoice_attr
передается этой фабрике в определенииChoiceType
(если вы не поставляете своиChoiceList
конечно) - person user2268997   schedule 18.08.2015