Symfony, how to use form event to validate dynamic client-side form

自闭症网瘾萝莉.ら 提交于 2019-12-25 10:40:51

问题


I'm using the select2 plugin with ajax to have a dynamic field on my form, but when i submit the it return me an error "This value is not valid", which is normal cause i use the ChoiceType with an empty array() in the choices options on creation. According to this part of the symfony doc, the form event is my savior, so trying to use it but it look like something wrong with my code and can't really see what.

So My Question Is :

HOW to pass the choices possibility to the field, for the form to be valid.

My form Type

class ArticleType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            //My other field

        //My functions to add the field with the possible choices
        $formModifier = function (FormInterface $form, $imageValue) use ($options) {
            if ($imageValue !== null) {
                $listImages = $this->getChoiceValue($imageValue, $options);

                if (!$listImages) {
                    $form->get('image')->addError(new FormError(
                    'Nous n\'avons pas pu trouver l\'image, veuiller choisir une autre'
                    ));
                }
            } else {
                $listImages = array();
            }

            //die(var_dump($listImages)); //Array of Image

            $form->add('image', ChoiceType::class, array(
                'attr' => array(
                    'id' => 'image'),
                'expanded' => false,
                'multiple' => false,
                'choices' => $listImages));
        };

        $formModifierSubmit = function (FormInterface $form, $imageValue) use ($options) {
            if ($imageValue !== null) {
                $listImages = $this->getChoiceValue($imageValue, $options);

                if (!$listImages) {
                    $form->get('image')->addError(new FormError(
                        'Nous n\'avons pas pu trouver l\'image, veuiller choisir une autre'
                    ));
                }
            } else {
                $form->get('image')->addError(new FormError(
                    'Veuillez choisir une image s.v.p.'
                ));
            }

            //die(var_dump($listImages)); //Array of Image object

            $config = $form->get('image')->getConfig();
            $opts = $config->getOptions();
            $chcs = array('choices' => $listImages);
            //die(var_dump($chcs)); //output an array with a 'choices' keys with array value
            array_replace($opts, $chcs); //not work
            //array_merge($opts, $chcs); //not work
            //die(var_dump($opts)); //replacements/merge are not made
        };

        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function (FormEvent $event) use ($formModifier) {
                // this would be the entity Article
                $data = $event->getData();

                $formModifier($event->getForm(), $data->getImage());
            }
        );

        //$builder->get('image')->addEventListener( //give error cause the field image don't exist
        $builder->addEventListener(
            FormEvents::PRE_SUBMIT,
            function (FormEvent $event) use ($formModifierSubmit) {
                $imageVal = $event->getData();
                //die(var_dump($imageVal)); //return all the submitted data field in an array
                //But when change this event to Submit it return the Article model populated by the submitted data, EXCEPT the image field which have null as value

                $formModifierSubmit($event->getForm(), $imageVal['image']);
            }
        );
    }

    public function getChoiceValue($imageValue, $options)
    {
        $listImages = $options['em']->getRepository('AlmotivAppBundle:Image')->findBy(array(
            'id' => $imageValue
        ));

        return $listImages; //array of Image object
    }
    [...]
}

For Info

My image field is not depending on any other field like the doc example, so i need to populate the choices options on PRE_SUBMIT event to give the possible choice.

And also image have a ManyToOne relation in my Article entity

class Article implements HighlightableModelInterface
{
    //some properties
    /**
     * @ORM\ManyToOne(targetEntity="Image\Entity\Path", cascade={"persist"})
     * @Assert\Valid()
     */
    private $image;
}

If i'm in the bad way let me know cause i'm out of idea now, i try much thing, like

  • array_replace with the options in the configuration of the field but didn't wrong.
  • make an ajax request to the url of the form action url : $form.attr('action'), i think it will load the choices option with the possible of <option> but my select is still returned with none <option>.

and much more (can't remmenber).

And also i'm using the v3.1 of the framework with the v4.0.3 of the select2 plugin, if need more info just ask and thx for reading and trying help.

Edit

Just add some info to be more clear


回答1:


You making things way too complicated. In your documentation example they add eventListener for already existing form field ('sport') and you are adding it to only later added field which does not exist (your 'image' field and 'position' field from the documentation example).

You should use EntityType and if you need (which I'm not if sure you are) filter your images using query_builder option, for validation add constraints (example with controller).

class ArticleType extends AbstractType {
/**
 * {@inheritdoc}
 */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

         // $builder
         // My other field
         $imageFieldFunction = $this->getImageFieldFunction();

         $builder->addEventListener(FormEvents::PRE_SET_DATA, $imageFieldFunction);
         $builder->addEventListener(FormEvents::PRE_SUBMIT, $imageFieldFunction);

    }
    private function getImageFieldFunction()
    {
         return function(FormEvent $event) {
             $form = $event->getForm();
             $data = $event->getData();
             //when your data_class is Article 
             $image = $data->getImage();//depending on your Article class
             /*if you are using data_class => null
             $image = $data['image'];
              */
             $imageId = $image ? $image->getId() : 0;

             $builder->add('image', EntityType::class , array(
            'class' => 'AlmotivAppBundle:Image',
             'attr' => array(
                'id' => 'image'
             ) ,
             'expanded' => false,
             'multiple' => false,
             'constraints' => new NotBlank(),
             'query_builder' => function (EntityRepository $er) use ($imageId) {
                  return $er->createQueryBuilder('i')
                            ->where('i.id = :image_id')
                            ->setParameter('image_id', $imageId);
             }

         ));
         }
    }
}


来源:https://stackoverflow.com/questions/44619386/symfony-how-to-use-form-event-to-validate-dynamic-client-side-form

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!