2012-07-24 18 views
7

Me gustaría usar un enunciado condicional al crear un formulario en Symfony.Usar un enunciado condicional al crear un formulario

Estoy usando un widget de elección en caso general. Si el usuario selecciona la opción "Otro", me gustaría mostrar un widget de cuadro de texto adicional . Supongo que esto se puede hacer en javascript, pero ¿cómo puedo persistir aún los datos de 2 widgets en la misma propiedad en mi entidad?

tengo esto hasta ahora:

$builder->add('menu', 'choice', array(
     'choices' => array('Option 1' => 'Option 1', 'Other' => 'Other'), 
     'required' => false, 
    )); 
    //How to add text box if choice == Other ???? 

estaba planeando utilizar un DataTransfomer, pero en 2 reproductores ??

Respuesta

33

Recomiendo crear un tipo personalizado para eso, por ejemplo ChoiceOrTextType. A este tipo agrega la opción (llamada "elección") y el campo de texto (llamado "texto").

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\OptionsResolver\OptionsResolverInterface; 

class ChoiceOrTextType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('choice', 'choice', array(
       'choices' => $options['choices'] + array('Other' => 'Other'), 
       'required' => false, 
      )) 
      ->add('text', 'text', array(
       'required' => false, 
      )) 
      ->addModelTransformer(new ValueToChoiceOrTextTransformer($options['choices'])) 
     ; 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setRequired(array('choices')); 
     $resolver->setAllowedTypes(array('choices' => 'array')); 
    } 
} 

Como ya adivinado, también es necesario un transformador de datos, que puede ser bastante simple:

use Symfony\Component\Form\DataTransformerInterface; 

class ValueToChoiceOrTextTransformer implements DataTransformerInterface 
{ 
    private $choices; 

    public function __construct(array $choices) 
    { 
     $this->choices = $choices; 
    } 

    public function transform($data) 
    { 
     if (in_array($data, $this->choices, true)) { 
      return array('choice' => $data, 'text' => null); 
     } 

     return array('choice' => 'Other', 'text' => $data); 
    } 

    public function reverseTransform($data) 
    { 
     if ('Other' === $data['choice']) { 
      return $data['text']; 
     } 

     return $data['choice']; 
    } 
} 

Ahora sólo hacen el "menú" campo de un campo de ese tipo.

$builder->add('menu', new ChoiceOrTextType(), array(
    'choices' => array('Option 1' => 'Option 1', 'Option 2' => 'Option 2'), 
    'required' => false, 
)); 
+2

Gracias bernhard. Estoy muy contento de que hayas tomado el tiempo para ayudarme con esto. Esta es una respuesta increíble y muy detallada, me gustaría poder poner +100. Todo tiene sentido ahora. Muchas gracias por el trabajo que ha realizado en el componente Formulario, esta es una herramienta INCREÍBLE y muy poderosa. Gracias. – Mick

+0

Como probablemente ya descubrió, había un ''Otro' => 'Otro' demasiado en la última muestra del código. Lo eliminé ahora. –

+0

Creo que en 'transform()', si los datos son nulos, entonces la matriz no debería ser devuelta, de lo contrario se seleccionará otra de manera predeterminada – ncatnow

Cuestiones relacionadas