Symfony2 - Dynamic form choices - validation remove
Asked Answered
M

5

13

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?

Mcginnis answered 13/8, 2013 at 11:6 Comment(0)
M
7

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

}
Mcginnis answered 14/8, 2013 at 9:1 Comment(3)
I'm running the same problem and I use DataTransformer to fix it but without success so I'll use this approach. Since the data is built in a controller by using a AJAX call, how I can populate the $choices array? Any advice?Halleyhalli
Thanks for this answer. More detailed example of this approach (albeit using PRE_SUBMIT): showmethecode.es/php/symfony/symfony2-4-dependent-formsFuture
And subtly different example (secondary field only added to form after primary field is submitted, using POST_SUBMIT) from the Symfony docs: symfony.com/doc/current/cookbook/form/…Future
A
0

The validation is handled by the Validator component: http://symfony.com/doc/current/book/validation.html.

The required option in the Form layer is used to control the HTML5 required attribute, so it won't change anything for you, and that is normal.

What you should do here is to configure the Validation layer according to the documentation linked above.

Allegro answered 13/8, 2013 at 13:14 Comment(4)
not sure I understand what you mean by configure validation layer?Mcginnis
I have read the documentation and tried adding a validation with min - max constraints of 0 and 255 and it doesnt work. It still wants only options from a pre-set list.Mcginnis
Ok, so I guess this may help you: symfony.com/doc/current/cookbook/form/….Allegro
i just want to disable the validation that seems like going around the houses and making it more complex than it needs to be.Mcginnis
C
0

Found a better solution which I posted here: Disable backend validation for choice field in Symfony 2 Type

Old answer:

Just spent a few hours dealing with that problem. This choice - type is really annoying. My solution is similar to yours, maybe a little shorter. Of course it's a hack but what can you do...

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('place', 'choice'); //don't validate that

    //... more form fields

   //before submit remove the field and set the submitted choice as
   //"static" choices to make "ChoiceToValueTransformer" happy
   $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
        $data = $event->getData();
        $form = $event->getForm();
        if ($form->has('place')) {
            $form->remove('place');
        }

        $form->add('place', 'choice', array(
            'choices' => array($data['place']=>'Whatever'),
        ));
    });
}
Claude answered 5/8, 2015 at 11:3 Comment(0)
E
0

Add this inside buildForm method in your form type class so that you can validate an input field value rather a choice from a select field value;

$builder->addEventListener(
    FormEvents::PRE_SUBMIT,

    function (FormEvent $event) {
        $form = $event->getForm();

        if ($form->has('verified_city')) {
            $form->remove('verified_city');
            $form->add(
                'verified_city', 
                'text', 
                ['required' => false]
            )
        }
    }
);
Eponym answered 23/8, 2017 at 1:1 Comment(0)
S
-1

Update in Validations.yml

Kindly update the Validation.yml file in the below format : setting the group names in the each field

 
         password:
            - NotBlank: { message: Please enter password ,groups: [Default]}
Update in Form Type /** * @param OptionsResolverInterface $resolver */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'RegistrationBundle\Entity\sf_members', 'validation_groups' => function(FormInterface $form){
$data = $form->getData();
$member_id = $data->getMemberId();

// Block of code; // starts Here :

if( condition == 'edit profile') { return array('edit'); } else { return array('Default'); } },

Update in Entity /** * @var string * * @ORM\Column(name="password", type="text") * @Assert\Regex( * pattern="/(?i)^(?=.[a-zA-Z])(?=.\d).{8,}$/", * match=true, * message="Your password must be at least 8 characters, including at least one number and one letter", * groups={"Default","edit"} * ) */
private $password;

Sparoid answered 28/3, 2016 at 13:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.