2012-07-24 22 views
7

oluştururken bir koşullu deyimi kullanın ben Symfony'de bir formu oluştururken bir koşullu deyimi kullanmak istiyorum.bir form

Ben genel durumda bir seçim aracını kullanıyorum. Kullanıcıların bu seçeneği "Diğer" seçerse, ben ek metin kutusu widget'ı görüntülemek istiyoruz. Bunun javascript ile yapılabildiğini varsayalım, fakat 2 widget'lardan elde ettiğim verileri şirketimde aynı mülke nasıl devam ettirebilirim?

ben bunun şimdiye kadar var:

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

Bir DataTransfomer kullanmak için planya, ancak 2 widget üzerinde oldu ??

cevap

33

Ben örneğin ChoiceOrTextType için, bunun için özel bir türü oluşturmak için önerilir. Bu türe hem seçim ("seçim" olarak adlandırılır) hem de metin alanını ("metin" olarak adlandırılır) eklersiniz.

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

Artık sadece "menü" bu tür bir alan alanına olun: Zaten tahmin gibi

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

, ayrıca oldukça basit olabilir, bir veri trafo, gerekir.

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

Teşekkürler bernhard. Bana yardımcı olmak için zaman ayırdığınıza çok sevindim. Bu müthiş ve çok detaylı bir cevap, keşke +100 koyabileyim. Artık her şey mantıklı. Form bileşeni üzerinde yaptığınız iş için çok teşekkürler, bu bir ŞAŞIRTICI ve çok güçlü bir araçtır. Teşekkürler. – Mick

+0

Muhtemelen daha önce öğrendiğiniz gibi, son kod örneğinde çok fazla "Diğer" => "Diğer" vardı. Bunu şimdi kaldırdım. –

+0

"Transform()" ifadesinde, veriler boşsa, dizinin döndürülmemesi gerektiğini düşünüyorum, aksi halde Diğer varsayılan olarak seçilecektir – ncatnow