Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Symfony] Champ dynamique dans formulaire imbriqué

Sujet résolu
    10 janvier 2020 à 15:06:46

    Bonjour,

    j'ai un projet Symfony avec une demande un peu spéciale.

    Je possède un formulaire qui imbrique un autre formulaire via une collectionType (mon formulaire Seance imbrique un formulaire Indication) :

    ->add('indications', CollectionType::class, [
                    'label' => false,
                    'entry_type' => IndicationType::class,
                    'entry_options' => ['label' => false],
                    'allow_add' => true,
                    'allow_delete' => true,
                    //'prototype' => true,
                    //'prototype_data' => 'New Tag Placeholder',
                ])

    La vue :

        <div class="col-12 col-sm-6">
           <div class="dt-card">
                <div class="dt-card__body">
                    <h4>Indication(s)</h4><hr>
                    {% if form.indications is defined %}
                        <div id="seance_indications" data-prototype="
                        {% apply escape %}
                        {% include 'seance/_proto.html.twig' with { 'form': form.indications.vars.prototype } only %}
                        {% endapply %}
                        ">               
                            {% for item in form.indications %}
                                {% include 'seance/_proto.html.twig' with { 'form': item } only %}
                            {% endfor %}
                        </div>
                    {% endif %}
                    <a href="#" id="add_indications" class="btn btn-info btn-sm">Ajouter une indication</a>
                </div>
            </div>
        </div>
    </div>

    Jusque la tout va bien, je ne mets pas le code JS pour la génération des formulaires imbriqués lors d'un clique sur un bouton afin d'en ajouter indéfiniment.

    Maintenant ça se complique. Dans mon formulaire qui est imbriqué (donc Indication), j'ai un champ de sélection multiple qui doit s'afficher en fonction d'un autre champ de sélection.

    Lorsque mon champ diagnostic est sélectionné, le champ diagnosticSecondaires doit se pré-remplir dynamiquement en fonction de la valeur sélectionné dans le champ diagnostic.

    Pour ce faire j'ai donc suivi la documentation. Voici mon formulaire imbriqué IndicationType :

    <?php
    
    namespace App\Form;
    
    use App\Entity\Diagnostic;
    use App\Entity\Indication;
    use Doctrine\ORM\EntityRepository;
    use App\Entity\DiagnosticSecondaire;
    use Symfony\Component\Form\FormEvent;
    use Symfony\Component\Form\FormEvents;
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\FormInterface;
    use Symfony\Component\Form\FormBuilderInterface;
    use Symfony\Bridge\Doctrine\Form\Type\EntityType;
    use Symfony\Component\OptionsResolver\OptionsResolver;
    use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
    use Symfony\Component\Form\Extension\Core\Type\TextareaType;
    
    class IndicationType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('commentaire', TextareaType::class, [
                    'label' => "Commentaire",
                    'required' => false,
                    'attr' => [
                        'class' => 'form-control-sm',
                        'rows' => 5
                    ]
                ])
                ->add('type', ChoiceType::class, [
                    'placeholder' => '-- Votre choix --',
                    'required' => false,
                    'label' => 'Type',
                    'expanded' => false,
                    'multiple' => false,
                    'choices' => [
                        'Aigu' => 'Chronique',
                        'Chronique' => 'Chronique'
                    ],
                    'attr' => [
                        'class' => 'form-control-sm'
                    ]
                ])
                ->add('diagnostic', EntityType::class, [
                    'required' => false,
                    'class' => Diagnostic::class,
                    'placeholder' => '-- Votre choix --',
                    'label' => 'Diagnostic principal',
                    'attr' => [
                        'class' => 'form-control-sm select2'
                    ],
                    'query_builder' => function (EntityRepository $er) {
                        return $er->createQueryBuilder('d')
                            ->where("d.statut = 1")
                            ->orderBy('d.nom', 'ASC');
                    },
                    'choice_label' => function ($diagnostic) {
                        return ucfirst($diagnostic->getNom());
                    }
                ])
            ;
    
            $formModifier = function (?FormInterface $form, Diagnostic $diagnostic = null) {
                $diagnosticSecondaires = null === $diagnostic ? [] : $diagnostic->getDiagnosticSecondaires();
    
                $form->add('diagnosticSecondaires', EntityType::class, [
                    'required' => false,
                    'class' => DiagnosticSecondaire::class,
                    'multiple' => true,
                    'label' => 'Diagnostic(s) secondaire(s)',
                    'attr' => [
                        'class' => 'form-control-sm select2'
                    ],
                    'choices' => $diagnosticSecondaires,
                    'query_builder' => function (EntityRepository $er) {
                        return $er->createQueryBuilder('d')
                            ->where("d.statut = 1")
                            ->orderBy('d.nom', 'ASC');
                    },
                    'choice_label' => function ($diagnosticSecondaire) {
                        return ucfirst($diagnosticSecondaire->getNom());
                    }
                ]);
            };
    
    
            $builder->addEventListener(
                FormEvents::PRE_SET_DATA,
                function (FormEvent $event) use ($formModifier) {
                    $data = $event->getData();
                    $formModifier($event->getForm(), $data->getDiagnostic());
                }
            );
    
            $builder->get('diagnostic')->addEventListener(
                FormEvents::POST_SUBMIT,
                function (FormEvent $event) use ($formModifier) {
                    $diagnostic = $event->getForm()->getData();
                    $formModifier($event->getForm()->getParent(), $diagnostic);
                }
            );
        }
    
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults([
                'data_class' => Indication::class,
            ]);
        }
    }
    

    Problème : j'obtiens une erreur :




    $event->getData() est toujours null dans le PRE_SET_DATA...

    J'ai cherché sur le net, mais je ne trouve pas la solution exact. Le problème viendrait du formulaire imbriqué avec le collection Type et notamment avec le allow_add => true (que je veux garder à true).

    Merci d'avance

    [RESOLU] avec ceci :

          $builder->addEventListener(
                FormEvents::PRE_SET_DATA,
                function (FormEvent $event) use ($formModifier) {
                    $data = $event->getData();
                    $var = ($data == null) ? null : $data->getDiagnostic();
                    $formModifier($event->getForm(), $var);
                }
            );



    -
    Edité par romsVLM 10 janvier 2020 à 16:30:17

    • Partager sur Facebook
    • Partager sur Twitter
      20 octobre 2020 à 10:01:49

      Un ti up, j ai le meme probleme SVP. J avais pas vu la réponse sry

      -
      Edité par GhislainMichel 20 octobre 2020 à 10:02:55

      • Partager sur Facebook
      • Partager sur Twitter

      [Symfony] Champ dynamique dans formulaire imbriqué

      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
      • Editeur
      • Markdown