修改Symfony表单html属性/覆盖单个属性

时间:2014-02-27 02:59:36

标签: symfony symfony-forms

我试图弄清楚如何使用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属性?

3 个答案:

答案 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”和标签:“我的表单占位符”。