27

在 symfony 1.4 中,可以通过表单的选项参数化表单类定义。有没有办法将自定义选项传递给我的自定义表单类型???我尝试使用该buildForm方法的 options 参数,但我不太确定这个数组是什么,显然它不是我想要的......谢谢!

4

6 回答 6

43

解决方案很简单,如果您希望您的自定义选项也可以在 Twig 模板中使用,您也必须使用 方法$builder->setAttribute()中的buildForm方法和 $view->set()方法中的buildView()方法。

<?php

namespace Acme\DemoBundle\Form\Type;

use Symfony\Component\Form\AbstractType as FormAbstractType;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;

// For Symfony 2.1 and higher:
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
 * ImagePreviewType
 *
 */
class ImagePreviewType extends FormAbstractType
{

    /**
     * {@inheritDoc}
     * For Symfony 2.0
     */
    //public function getDefaultOptions(array $options)
    //{
    //    $options = parent::getDefaultOptions($options);
    //    $options['base_path'] = 'path/to/default/dir/';
    //
    //    return $options;
    //}

    /**
     * {@inheritDoc}
     * For Symfony 2.1 and higher
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'base_path'         => '',
        ));
    }

    /**
     * {@inheritDoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        // For Symfony 2.0:
        // $view->set('base_path', $form->getAttribute('base_path'));

        // For Symfony 2.1 and higher:
        $view->vars['base_path'] = $options['base_path'];
    }

    /**
     * {@inheritDoc}
     */
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder
            ->setAttribute('base_path', $options['base_path'])
        ;
    }

    /**
     * {@inheritDoc}
     */
    public function getName()
    {
        return 'image_preview';
    }

    public function getParent(array $options)
    {
        // for Symfony 2.0:
        // return 'field';

        // for Symfony 2.1 and higher:
        return 'form';
    }
}

自定义表单类型的模板(文件 ...Acme/DemoBundle/Resources/views/Form/fields.html.twig):

{% block image_preview_widget %}
{% spaceless %}
<img src="{{ base_path ~ value }}" alt=""  {{ block('widget_container_attributes') }} />
{% endspaceless %}
{% endblock %}

在 app/config/config.yml 中为自定义表单类型注册您的模板

twig:
    debug:            %kernel.debug%
    strict_variables: %kernel.debug%
    form:
        resources:
            - 'AcmeDemoAdminBundle:Form:fields.html.twig'

用法:在编辑他的个人资料时显示用户图像的预览:

// src/Acme/DemoBundle/Form/Type/UserType.php
namespace Acme\DemoBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;

class UserType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder->add('user_profile_image_file_name', new ImagePreviewType(), array(
            'base_path' => 'some/other/dir',
        ));
    }
}

2014-08-18:为 Symfony 2.1 或更高版本更新

于 2012-07-11T22:44:38.777 回答
18

更新:请注意,此解决方案仅适用于 Symfony 2.0.x,它已过时,使用setDefaultOptions而不是getDefaultOptions.


恰如其分,Symfony 2 表单类型接受选项,您可以在表单类型中使用您想要的任何内容。您需要覆盖getDefaultOptions方法来指定您的类型选项。

例如,我有一个MyCustomType接受的类型my_option,这个选项有一个默认值false,的实现MyCustomType可以是这样的。

class MyCustomType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        if($options['my_option']){
            //do something
        } else {
            //do another thing
        }
        ...
    }

    public function getDefaultOptions(array $options)
    {
        return array(
            'my_option' => false
        );
    }

    public function getName()
    {
        return 'mycustomtype';
    }
}

稍后,您将需要在控制器中创建表单时指定选项,使用的第三个参数buildForm

$form = $this->buildForm(new MyCustomType(), null, array(
    'my_option' => true
));

如果您未指定该my_option选项,则它采用默认值 ( false)。

于 2012-06-06T21:47:59.917 回答
10

使用 symfony 2.8,我成功地使用了扩展该configureOptions()方法的建议解决方案。

class ElementType extends AbstractType
{
    // ...

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'my_custom_option_parameter' => null,
        ));
    }
}

我需要使用ElementType, 作为集合和嵌入式表单。我认识到不可能将 传递my_custom_option_parameterCollectionType,因为我不是自定义configureOptions()CollectionType,而是我的ElementType. 如果您需要my_custom_option_parameter通过. CollectionType_ _ _my_custom_option_parameterentry_optionsCollectionType

my_custom_option_parameter通过 a 的示例CollectionType

class OuterFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    { 
        //...
        $builder->add('elements', CollectionType::class, array(
            'entry_type' => ElementType::class,
            // ...
            'entry_options' => array(
                'my_custom_option_parameter' => 'value is now set!'
            )
        ));
        //...
    }
}
于 2016-04-05T20:07:40.067 回答
5

基于@pulzarraider 的回答,我为 Symfony 3 创建了带有更改的代码。

你需要改变

OptionsResolverInterface为了OptionsResolver

FormBuilder为了FormBuilderInterface

就我而言:

namespace MediaBundle\Form;

use Symfony\Component\Form\AbstractType as FormAbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\FormBuilderInterface;

class ImageType extends FormAbstractType {

    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults(array(
            'max_images' => ''
        ));
    }

    public function buildView(FormView $view, FormInterface $form, array $options) {

        $view->vars['max_images'] = $options['max_images'];
    }

    public function buildForm(FormBuilderInterface $builder, array $options) {

        $builder
                ->setAttribute('max_images', $options['max_images'])
        ;
    }

    public function getName() {
        return 'image_preview';
    }

    public function getParent() {
        return TextareaType::class;
    }
}
于 2016-12-28T21:55:57.210 回答
3

使用 Symfony 3,我可以通过在注入到我的表单类型类的 configureOptions 方法中的 OptionsResolver 中设置默认选项来将自定义选项传递给表单:

在控制器中:

//Compile whatever your options are here. Assume an array is returned
$customOptions = $this->getMyCustomOptions($args);
//Build the form:
$form = $this->createForm(MyCustomFormType::class, array('my_custom_options' => $customOptions));

MyCustomFormType.php:

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults([
        'data_class' => DataModel::class,
        'my_custom_options' => []
    ]);
}
//custom options is now set in "$options" array:
public function buildForm(FormBuilderInterface $builder, array $options) {
    $builder->add('my_custom_fields', Type\ChoiceType::class, [
       'choices' => $options['my_custom_options'],
       'mapped' => false //if not part of the data model.
       . . .

因此,看起来您可以与表单和数据提供者定义合同以在表单上设置任意数据。

我刚刚成功实施了这个程序。请注意,在回程中,由于您已'mapped' => false,在 formBuilder 中设置,$form->getData()因此不会返回选择。要获取选定的值:

$mySelectedValue = $form->get('my_custom_options')->getViewData();

在您的控制器中。为什么这是我无法理解的。. .

于 2016-09-20T19:07:15.597 回答
2

我尝试使用该选项array但没有成功,因为它似乎只能携带少量的预定义键子集。无论如何,这对我来说是不可接受的......

但是,您可以通过 forms__construct方法传递所有选项并将其存储在类属性中以供以后使用。然后,buildForm您可以使用$this->"propertyName"...访问它

由您决定是否要将单个array或几个变量传递给__construct...

这只是一个粗略的例子:

class Foobar{
    private $update = false;

    public function __construct($update = false){
        $this->update = $update;
    }


    public function buildForm(FormBuilder builder, array options){
        if ( $update ){
            // something
        }else{
            // well, this is not an update - do something else
        }
    }
}
于 2012-06-06T21:17:09.993 回答