我试图弄清楚如何使用Symfony2表单动态修改html属性。
这种情况是大多数时间都使用默认占位符的情况,但有时候,开发人员需要编写自定义消息。
我的表单类型如下所示:
<?php
namespace My\AwesomeBundle\FormType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use My\AwesomeBundle\Transformer\ProcedureCodeTransformer;
class ProcedureType extends AbstractType
{
private $em;
private $user;
public function __construct($em, $securityContext)
{
$this->em=$em;
$this->user=$securityContext->getToken()->getUser();
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$transformer = new ProcedureTransformer( $this->em );
$builder->addModelTransformer( $transformer );
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$user = $this->user;
$resolver->setDefaults(
array(
'class' => 'My\AwesomeBundle\Entity\Procedure',
'label' => 'Procedure',
'label_attr' => array( 'class'=> 'control-label' ),
'required' => false,
'empty_value' => '',
'attr' => array(
'class' => 's2',
'data-select2-placeholder' => 'Select Procedure',
),
)
);
$resolver->setOptional( array( 'placeholder' ) );
}
public function getParent() {
return 'hidden';
}
public function getName() {
return 'procedure';
}
}
默认渲染然后对data-select2-placeholder元素有“Select Procedure”,javascript用于显示它。然后将其用于更复杂的类型:
<?php
namespace My\AwesomeBundle\FormType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class ProcedureType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options){
$builder->add('biller', 'billers', array( 'placeholder' => 'New Text'));
[...]
}
public function setDefaultOptions(OptionsResolverInterface $resolver){
$resolver->setDefaults( array(
'data_class' => 'My\AwesomeBundle\Entity\Procedure'
) );
}
public function getName(){
return 'my_awesomebundle_proceduretype';
}
}
我希望将“新文本”放入data-select2-placeholder html属性中。但是,如果我这样打电话给建设者:
$builder->add('procedure',
new ProcedureCodeType()),
array( 'attr' => array('data-select2-placeholder' => 'New Text') )
);
替换整个html属性数组。这并不奇怪。表单构建器中是否有一个函数让我无法添加或修改单个html属性?
答案 0 :(得分:7)
不幸的是,没有办法按照你想要的方式修改单个attr。这是我能提供的最接近,最简单的解决方案:
在您的情况下,您需要做的是在选项中使用回调函数。
对于表单类型中的每个默认属性,而不是正常值,您可以使用一个回调函数来接受表示您的选项的单个输入(Symfony类 Symfony \ Component \ OptionsResolver \ Options ) 。在构建表单时调用该函数,然后将返回值用作选项的值。
这样,您可以根据其他提供的选项构建结果选项。一个例子:
use Symfony\Component\OptionsResolver\Options;
class ProcedureType extends AbstractType
{
...
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$attr = function(Options $options) {
$default = array(
'class' => 's2',
'data-select2-placeholder' => 'Select Procedure',
);
return array_replace($default, $options['new_attr']);
};
$user = $this->user;
$resolver->setDefaults(
array(
'class' => 'My\AwesomeBundle\Entity\Procedure',
'label' => 'Procedure',
'label_attr' => array( 'class'=> 'control-label' ),
'required' => false,
'empty_value' => '',
'attr' => $attr,
'new_attr' => array(),
)
);
$resolver->setOptional( array( 'placeholder' ) );
}
这样,您需要修改的内容将是 new_attr 。
答案 1 :(得分:1)
您可能想要创建一个新的类来解析嵌套选项。
<?php
namespace My\AwesomeBundle\Form\Attr;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\OptionsResolver\Options;
class ProcedureCodeAttr
{
/**
* @var array
*/
protected $options;
/**
* @param array $options
*/
public function __construct(array $options = array())
{
$resolver = new OptionsResolver();
$this->setDefaultOptions($resolver);
$this->options = $resolver->resolve($options);
}
/**
* @param OptionsResolverInterface $resolver
*/
protected function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'class' => 's2',
'data-select2-placeholder' => 'Select Procedure',
));
}
/**
* @return array
*/
public function toArray()
{
return $this->options;
}
/**
* @param array $options
* @return array
*/
public static function resolve(array $options = array())
{
$attr = new static($options);
return $attr->toArray();
}
}
然后在你的表单类型类中,你会像这样使用它
$builder->add('procedure', new ProcedureCodeType()), array(
'attr' => ProcedureCodeAttr::resolve(array(
'data-select2-placeholder' => 'New Text'
))
));
答案 2 :(得分:0)
Symfony 4.4及更高版本现在支持嵌套选项https://symfony.com/doc/4.4/components/options_resolver.html#nested-options
使用OptionsResolver
创建回调来代替定义嵌套数组。
例如,存在具有以下默认值的自定义表单类型:
class CustomType extends AbstractType {
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('attr', function (OptionsResolver $attrResolver) {
$attrResolver->setDefaults([
'class' => 'form-control-lg',
'placeholder' => 'My Default Placeholder',
'autocomplete' => 'off',
]);
});
$resolver->setDefaults([
'label' => 'Name',
'help' => 'Enter a name',
]);
}
....
}
Attr现在是一个回调,而不是数组,现在以任何形式使用它都可以像普通一样定义attr属性。
class MyFormType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', CustomType::class, [
'label' => 'My Form',
'help' => 'My Form Help',
'attr' => [
'placeholder' => 'My Form Placeholder',
],
])
....
}
生成的表单将具有类:“ form-control-lg”和标签:“我的表单占位符”。