Pasar opciones personalizadas a una forma symfony2

en Symfony 1.4 fue posible parametrizar una definición de clase de formulario, a través de las opciones de la forma. ¿Hay alguna forma de pasar opciones personalizadas a mi tipo de formulario personalizado ??? He intentado usar el parámetro buildForm método buildForm , pero no estoy muy seguro de qué es esta matriz, y aparentemente no es lo que quiero … ¡Gracias!

La solución es simple, si quiere que su opción personalizada esté disponible también en la plantilla Twig, debe usar $builder->setAttribute() en el método buildForm y el método $view->set() en el método buildView() también.

 < ?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'; } } 

Plantilla para el tipo de formulario personalizado (archivo … Acme / DemoBundle / Resources / views / Form / fields.html.twig):

 {% block image_preview_widget %} {% spaceless %}  {% endspaceless %} {% endblock %} 

Registre su plantilla para tipos de formularios personalizados en app / config / config.yml

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

Uso: muestra una vista previa de la imagen del usuario mientras edita su perfil:

 // 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', )); } } 

18-08-2014: actualizado para Symfony 2.1 o superior

ACTUALIZACIÓN: tenga en cuenta que esta solución solo funciona en Symfony 2.0.x, que está obsoleto, use setDefaultOptions lugar de getDefaultOptions .


Justamente, los tipos de formulario de Symfony 2 aceptan opciones que puede usar para cualquier cosa que desee dentro del tipo de formulario. getDefaultOptions sobrescribir el método getDefaultOptions para especificar sus opciones de tipo.

Por ejemplo, tengo un tipo MyCustomType que acepta my_option , esta opción tiene un valor predeterminado de false , la implementación de MyCustomType puede ser algo como esto.

 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'; } } 

Más adelante, deberá especificar la opción cuando cree el formulario en el controlador, utilizando el tercer parámetro de buildForm :

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

Si no especifica la opción my_option , toma el valor predeterminado ( false ).

Usando Symfony 2.8, tuve éxito al usar la solución propuesta extendiendo el método configureOptions() .

 class ElementType extends AbstractType { // ... public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( 'my_custom_option_parameter' => null, )); } } 

Necesitaba usar ElementType , como una colección y forma incrustada. Reconocí que no era posible pasar my_custom_option_parameter al CollectionType , porque no personalicé configureOptions() de CollectionType , sino de mi ElementType . Si necesita pasar my_custom_option_parameter través de un CollectionType , puede tener éxito definiendo my_custom_option_parameter en entry_options (vea Documentation CollectionType Field ) array of CollectionType .

Ejemplo que pasa my_custom_option_parameter través de un 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!' ) )); //... } } 

He intentado usar esa array opciones sin éxito, ya que parecía que solo podía llevar un pequeño subconjunto predefinido de claves. Esto fue, por supuesto, inaceptable para mí …

Sin embargo, puede pasar todas las opciones a través del método __construct formularios y almacenarlo en propiedades de clase para su uso posterior. Luego, desde buildForm puedes acceder utilizando $this->"propertyName"

__construct usted decidir si desea pasar una única array o solo unas pocas variables para __construct

Este es solo un ejemplo aproximado:

 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 } } } 

Utilizando Symfony 3, pude pasar opciones personalizadas al formulario estableciendo una opción predeterminada en OptionsResolver inyectado en el método configureOptions de mi clase de tipo de formulario:

En el controlador:

 //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. . . . 

Por lo tanto, parece que puede definir un contrato con su formulario y el proveedor de datos para establecer datos arbitrarios en el formulario.

Acabo de implementar con éxito este procedimiento. Tenga en cuenta que en el viaje de regreso, dado que ha configurado 'mapped' => false, en formBuilder, $form->getData() no devolverá la selección. Para obtener el valor seleccionado:

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

en tu controlador. Por qué esto está más allá de mí . .

basándome en la respuesta de @pulzarraider Creé el código con los cambios para Symfony 3.

Necesitas cambiar

OptionsResolverInterface para OptionsResolver

FormBuilder for FormBuilderInterface

En mi caso:

 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; } }