добавить прослушиватель событий в динамически добавляемое поле в Symfony3

Я использую прослушиватели событий для динамического изменения формы. Я хочу добавить во второе поле еще один прослушиватель событий. Я пробовал этот код, но он не работал:

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

       $builder
        ->add('Marque',   EntityType::class, array(
            'class'     =>  'EK\PlateformeBundle\Entity\Marque',
            'placeholder'   => '-- Choississez une marque --',
            //'mapped'    =>  false
        ))
        ->add('Modele',   EntityType::class, array(
            'class'     =>  'EK\PlateformeBundle\Entity\Modele',
            'placeholder'   => '-- Choississez un modèle --',
            //'mapped'    =>  false
        ))
        ->add('nom',   EntityType::class, array(
            'class'     =>  'EK\PlateformeBundle\Entity\Type',
            'placeholder'   => '-- Choississez une type --',
            //'mapped'    =>  false
        ))
    ;

    $formModifierM = function (FormInterface $form, Marque $marque = null) {

        $modeles = null === $marque ? array() : $marque->getAvailableModeles(); // only in a bidirectional relationship
        $placeholder = empty($modeles) ? '-- Choississez un modèle  --' : '';
        $form->add('Modele',  EntityType::class, array(
            'class' =>  'EK\PlateformeBundle\Entity\Modele',
            'placeholder'   => $placeholder,
            'choices' => $modeles,
        ))
            ->add('Rechercher',  SubmitType::class) ;

    };

    $formModifierModele = function (FormInterface $form, Modele $modele = null) {

        $types = null === $modele ? array() : $modele->getAvailableTypes(); // only in a bidirectional relationship
        $placeholder = empty($types) ? '-- Choississez un type  --' : '';
        $form->add('nom',  EntityType::class, array(
            'class' =>  'EK\PlateformeBundle\Entity\Type',
            'placeholder'   => $placeholder,
            'choices' => $types,
        ))
            ->add('Rechercher',  SubmitType::class) ;

    };


    $builder->addEventListener(
        FormEvents::PRE_SET_DATA,
        function(FormEvent $event) use ($formModifierM ,$formModifierModele){
            $form = $event->getForm();
            $formModifierM($form, null);
            $formModifierModele($form, null);
        }
    );

    $builder->get('Marque')->addEventListener(
        FormEvents::POST_SUBMIT,
        function(FormEvent $event) use ($formModifierM) {

            $form = $event->getForm()->getParent();
            $marque = $event->getForm()->getData();
            // since we've added the listener to the child, we'll have to pass on
            // the parent to the callback functions!
            $formModifierM($form, $marque);
        }

    );


    $builder->get('Modele')->addEventListener( // this code did'nt work 
        FormEvents::POST_SUBMIT,
        function(FormEvent $event) use ($formModifierModele) {

            $form = $event->getForm()->getParent();
            $modele = $event->getForm()->getData();
            $formModifierModele($form, $modele); 
        }
    );

}

Я не нашел решения этой проблемы. Любой может мне помочь. Я нашел тот же вопрос, но у меня он не сработал Как добавить прослушиватель событий в динамически добавляемое поле с помощью Symfony Forms.


person Sabra    schedule 08.08.2017    source источник


Ответы (2)


Я думаю, что лучше использовать цепные модификаторы и добавлять их с помощью NamedFormBuilder, как в примере ниже. Это связано с тем, что в событии PRE_SUBMIT вы обращаетесь к данным запроса, что в некоторых случаях может нарушить ваш код.

$volumeModifier = function(FormInterface $form, ?Vendor $vendor, ?int $year, ?int $volume): void {

        if (null === $volume) {
            return;
        }

        $form->add("model", EntityType::class, [
            "class"         => Model::class,
            "required"      => false,
            "query_builder" => function(ModelRepository $er) use ($vendor, $year, $volume) {

            // return builded qb;
            },
        ]);
    };

    $yearModifier = function(FormInterface $form, ?Vendor $vendor, ?int $year) use ($volumeModifier): void {

        if (null === $year) {
            return;
        }

        $volumes = [];//build volumes choices

        $builder =
            $form->getConfig()->getFormFactory()->createNamedBuilder("volume", ChoiceType::class, null, [
                "auto_initialize" => false,
                "required"        => false,
                "choices"         => $volumes,
            ]);

        $builder->addEventListener(
            FormEvents::POST_SUBMIT,
            function(FormEvent $event) use ($vendor, $year, $volumeModifier) {
                /** @var int $volume */
                $volume = $event->getForm()->getData();
                $volumeModifier($event->getForm()->getParent(), $vendor, $year, $volume);
            });

        $form->add($builder->getForm());
    };
$vendorModifier = function(FormInterface $form, ?Vendor $vendor) use ($yearModifier): void {

        if (null === $vendor) {
            return;
        }

        $years = [];// build years choices

        $builder =
            $form->getConfig()->getFormFactory()->createNamedBuilder("year", ChoiceType::class, null, [
                "auto_initialize" => false,
                "required"        => false,
                "choices"         => $years,
            ]);

        $builder->addEventListener(
            FormEvents::POST_SUBMIT,
            function(FormEvent $event) use ($vendor, $yearModifier) {
                /** @var int $year */
                $year = $event->getForm()->getData();
                $yearModifier($event->getForm()->getParent(), $vendor, $year);
            });

        $form->add($builder->getForm());
    };

    $builder->get("vendor")->addEventListener(
        FormEvents::POST_SUBMIT,
        function(FormEvent $event) use ($vendorModifier) {
            /** @var Vendor $vendor */
            $vendor = $event->getForm()->getData();
            $vendorModifier($event->getForm()->getParent(), $vendor);
        });
person wtorsi    schedule 13.10.2017

Я решил свою проблему. вот мой рабочий код: POST_SUBMIT необходимо заменить на PRE_SUBMIT

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

        /** @var \Doctrine\ORM\EntityManager $em */
       $em = $options['entity_manager'];

       $builder
        ->add('Marque',   EntityType::class, array(
            'class'     =>  'EK\PlateformeBundle\Entity\Marque',
            'placeholder'   => '-- Choississez une marque --',
             'required' => false,
            //'mapped'    =>  false
        ))
        ->add('Modele',   EntityType::class, array(
            'class'     =>  'EK\PlateformeBundle\Entity\Modele',
            'placeholder'   => '-- Choississez un modèle --',
             'required' => false,
            //'mapped'    =>  false
        ))
        ->add('nom',   EntityType::class, array(
            'class'     =>  'EK\PlateformeBundle\Entity\Type',
            'placeholder'   => '-- Choississez une type --',
             'required' => false,
            //'mapped'    =>  false
        ))
    ;

    $formModifierM = function (FormInterface $form, Marque $marque = null) {

        $modeles = null === $marque ? array() : $marque->getAvailableModeles(); // only in a bidirectional relationship
        $placeholder = empty($modeles) ? '-- Choississez un modèle  --' : '';
        $form->add('Modele',  EntityType::class, array(
            'class' =>  'EK\PlateformeBundle\Entity\Modele',
            'placeholder'   => $placeholder,
             'required' => false,
            'choices' => $modeles,
        ))
            ->add('Rechercher',  SubmitType::class) ;

    };

    $formModifierModele = function (FormInterface $form, Modele $modele = null) {

        $types = null === $modele ? array() : $modele->getAvailableTypes(); // only in a bidirectional relationship
        $placeholder = empty($types) ? '-- Choississez un type  --' : '';
        $form->add('nom',  EntityType::class, array(
            'class' =>  'EK\PlateformeBundle\Entity\Type',
            'placeholder'   => $placeholder,
             'required' => false,
            'choices' => $types,
        ))
            ->add('Rechercher',  SubmitType::class) ;

    };


    $builder->addEventListener(
        FormEvents::PRE_SET_DATA,
        function(FormEvent $event) use ($formModifierM ,$formModifierModele){
            $form = $event->getForm();
            $formModifierM($form, null);
            $formModifierModele($form, null);
        }
    );

   $builder->addEventListener(
        FormEvents::PRE_SUBMIT,
        function(FormEvent $event) use ($formModifierM ,$formModifierModele ,  $em) {
            $form = $event->getForm();
            $data = $event->getData();
           if (!isset($data['Modele']) || empty($data['Modele']))
           {

            $marque_id = $data['Marque'];
            $marque   = $em->getRepository("EK\PlateformeBundle\Entity\Marque")->find($marque_id);
            $formModifierM($form, $marque);
          }
          else
          {
              $modele_id = $data['Modele'];      
              $modele   = $em->getRepository("EK\PlateformeBundle\Entity\Modele")->find($modele_id);
              $formModifierModele($form, $modele);
          }

        }

    );



}
person Sabra    schedule 09.08.2017