Bonjour,

Je rencontre un petit problème avec mon code. Après avoir exécuté une requête AJAX pour modifier mon formulaire, les données du champ ne sont pas récupérée lors du submit.

Ce que je fais

J'ai suivi le tutoriel de Symfony pour modifier dynamiquement les options de mon champ "<select>" en fonction d'un autre champ.

Tutoriel symfony : How to Dynamically Modify Forms Using Form Events

Je vous donnes les parties concernées.

FileFormType

$builder
            ->add('Location', EntityType::class, [
                'required' => true,
                'label_attr' => [ ' class' => 'font-weight-bold'],
                'attr' => [
                    'class' => 'form-control'
                ],
                'placeholder' => 'Please choose a location',
                'class' => Locations::class,
            ])

            ->add('Court', EntityType::class, [
                'required' => true,
                'data' => $courts,
                'label_attr' => [ ' class' => 'font-weight-bold'],
                 'attr' => [
                     'class' => 'form-control'
                 ],
                 'choice_attr' => [
                   'class' => 'form-check-input'
                 ],
                 'placeholder' => 'Please choose a court',
                 'class' => Courts::class
             ])
            ;

        $addLocations = function(FormInterface  $form, Courts $courts = null ){
            $arrayCourts = null === $courts ? [] : $courts->getLocations();

            $form->add('Location', EntityType::class, [
                'required' => true,
                'label_attr' => [ ' class' => 'font-weight-bold'],
                'attr' => [
                    'class' => 'form-control'
                ],
                'placeholder' => 'Please choose a location',
                'class' => Locations::class,
                'choices' => $arrayCourts
            ]);
        };

        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function(FormEvent $event) use ($addLocations){
                $data = $event->getData();

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

                $addLocations($event->getForm(), $data->getLocations());
            }
        );

        $builder->get('Court')->addEventListener(
            FormEvents::POST_SUBMIT,
            function(FormEvent $event) use ($addLocations){
                $courts = $event->getForm()->getData();

                $addLocations($event->getForm()->getParent(), $courts);
            }
        );

Ajax (upload.html.twig)

var $form = $(this).closest('form');
            var data = {};
            data[$courts.attr('name')] = $courts.val();
            data[$courts.form()] = 'test';
            console.log(data);
            $.ajax({
                url: $form.attr('action'),
                type: $form.attr('method'),
                data: data,
                success: function(html){
                    $('#file_form_Location').replaceWith(
                    $(html).find('#file_form_Location')
                    );
                }
            });
         });

Ce que je veux

Je souhaite que lorsque le formulaire est envoyée, il récupère toutes les données de celui-ci.

Ce que j'obtiens

Avant l'exécution de ma requête AJAX,, mon champ est bien lié à mon "form".

form: <form name="file_form" method="post" enctype="multipart/form-data">

Après la requête, le form n'est plus attaché.

form: null

Une petite idée ? :p

7 réponses


Brandon Sauveniere
Auteur
Réponse acceptée

Problème résolu. J'ai simplement recréé mon entité et ça a fonctionné par miracle.

tu peux utiliser un Form Data pour mieux gérer le formulaire, essaie aussi de rebind le form après ta request

Bonjour Bernard Ngandu,

Justement, comment rebind le form après la requête?

$form = $(this).closest('form');

J'utilise déjà cette ligne dans la requête où je m'en sers pour définir la méthode et l'action du form. En plus de ça, que dois-je faire?

Moi je te proposerai d'écrire une fonction qui bind le formulaire et écoute l'event submit pour effectuer la request ajax, cette fonction doit être recurisive, car après la soumission du formulaire du doit reéxecuter la fonction pour rebind le formulaire perso j'ai un truc comme ça en js vanilla:

import axios from '../axios';
import {bindFormPlugins, createButtonLoader, removeButtonLoader} from "../functions/dom";
import {toast} from "./Alert";

export default class Form {
    constructor(forms) {
        forms.forEach(f => {
            const process = f.getAttribute('data-process-type');
            switch (process) {
                case 'registration':
                    this.handleRegistration(f);
                    break;
                default:
                    this.handleSubmit(f);
                    break;
            }
        });
    }

    handleRegistration = (container) => {
        this.handleSubmit(container);

        container.addEventListener('app:form:success', (e) => {
            window.location = e.detail.getAttribute('data-target-path');
        })
    }

    handleSubmit = (container) => {
        const url = container.getAttribute('data-url');

        const handleSubmitRequest = (container, url) => {
            const form = container.querySelector('form');
            const submitButton = container.querySelector('button[type="submit"]');
            bindFormPlugins(form);

            submitButton.addEventListener('click', async (e) => {
                try {
                    e.preventDefault()
                    createButtonLoader(submitButton)
                    const response = await axios.post(url, new FormData(form));

                    if (response.status === 201 || response.status === 202) {
                        container.dispatchEvent(new CustomEvent('app:form:success', {detail: response}));
                        return;
                    }

                    container.innerHTML = response.data.html;
                    handleSubmitRequest(container, url);
                } catch (e) {
                    console.error("Erreur lors de la création/édition =>", {e})
                    await toast("error", e.toString())
                    removeButtonLoader(submitButton, 'Envoyer')
                }
            });
        }

        (async () => {
            const response = await axios.get(url);
            container.innerHTML = response.data.html;
            handleSubmitRequest(container, url);
        })();
    }
}

Salut !

Pour être hônnete, j'y connais rien en AJAX. J'esperais que le tutorial de Symfony suffirait à lui-même. Bref, actuellement la requête AJAX écoute déjà le submit non? en tout cas, coté back, on a deux EventListener écoutant avant et après le submit. C'est ce qui permet d'afficher les bonnes données dans la liste déroulante.