Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony2 - Dynamic form choices - validation remove

I have a drop down form element. Initially it starts out empty but it is populated with values via javascript after the user has made some interactions. Thats all working ok. However when I submit it always returns a validation error This value is not valid..

If I add the items to the choices list in the form code it will validate OK however I am trying to populate it dynamically and pre adding the items to the choices list is not going to work.

The problem I think is because the form is validating against an empty list of items. I don't want it to validate against a list at all. I have set validation required to false. I switched the chocie type to text and that always passes validation.

This will only validate against empty rows or items added to choice list

$builder->add('verified_city', 'choice', array(
  'required' =>  false
));

Similar question here that was not answered.
Validating dynamically loaded choices in Symfony 2

Say you don't know what all the available choices are. It could be loaded in from a external web source?

like image 905
Robbo_UK Avatar asked Aug 13 '13 11:08

Robbo_UK


1 Answers

after much time messing around trying to find it. You basically need to add a PRE_BIND listener. You add some extra choices just before you bind the values ready for validation.

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;


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

  // .. create form code at the top

    $ff = $builder->getFormFactory();

    // function to add 'template' choice field dynamically
    $func = function (FormEvent $e) use ($ff) {
      $data = $e->getData();
      $form = $e->getForm();
      if ($form->has('verified_city')) {
        $form->remove('verified_city');
      }


      // this helps determine what the list of available cities are that we can use
      if ($data instanceof  \Portal\PriceWatchBundle\Entity\PriceWatch) {
        $country = ($data->getVerifiedCountry()) ? $data->getVerifiedCountry() : null;
      }
      else{
        $country = $data['verified_country'];
      }

      // here u can populate choices in a manner u do it in loadChoices use your service in here
      $choices = array('', '','Manchester' => 'Manchester', 'Leeds' => 'Leeds');

      #if (/* some conditions etc */)
      #{
      #  $choices = array('3' => '3', '4' => '4');
      #}
      $form->add($ff->createNamed('verified_city', 'choice', null, compact('choices')));
    };

    // Register the function above as EventListener on PreSet and PreBind

    // This is called when form first init - not needed in this example
    #$builder->addEventListener(FormEvents::PRE_SET_DATA, $func); 

    // called just before validation 
    $builder->addEventListener(FormEvents::PRE_BIND, $func);  

}
like image 98
Robbo_UK Avatar answered Sep 23 '22 20:09

Robbo_UK