Partage
  • Partager sur Facebook
  • Partager sur Twitter

Insérer formulaire PHP avec Ajax

16 septembre 2021 à 21:21:12

Bonjour,

Je travaille actuellement sur un devoir dans le cadre de ma formation, et je suis bloqué depuis plusieurs jours sur un problème que je n'arrive pas à résoudre. Le devoir en question m'a demandé de créer un formulaire en JavaScript lorsque l'on clique sur un bouton, puis de retourner depuis une page PHP une réponse lorsque l'on choisit une note dans le formulaire. Jusque-là tout va bien pour moi, mais c'est sur la troisième demande que je bloque.

Demande 3

Dans votre code JavaScript: ne générez plus le formulaire. Celui-ci sera généré par le PHP, sur demande du Javascript (requête Ajax): voir ci-dessous.

a) Lorsque la page est chargée (évènement onload), et que l’utilisateur clique sur le bouton “notation”, envoyez une requête au serveur php pour récupérer le HTML du formulaire et insérez-le dans le body. Cachez alors le bouton notation en lui affectant un attribut style (css) “display:none;”

b) Si l’utilisateur clique sur un nouveau bouton « close», cachez le formulaire et faites réapparaitre le bouton « notation». c) Si l’utilisateur reclique sur le bouton « notation», testez si le formulaire est déjà inséré dans le HTML. Si oui, réaffichez-le et cachez le bouton, sinon demandez (en JS) le formulaire en Ajax au serveur PHP. Le JavaScript doit être unobstusive. 

Mon formulaire a été écris dans la page PHP, mais j'ai beau essayer, je n'arrive pas à l'insérer dans la page HTML. Mes codes actuels :

index.html

<!DOCTYPE html>
<html lang="fr">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Correspondance américaine d'une note de musique</title>
        <script src="script.js"></script>
    </head>
    <body>
        <input type="button" id="notationBtn" value="Notation">
    </body>
</html>

form.php

<?php

    $usNote = $_GET['usNote'];
    $stdNote = $_GET['stdNote'];

    if ($usNote === '') {
        $result = 'Aucune note sélectionnée.';
    } else {
        $result = 'La note américaine pour la note '. $stdNote .' est '. $usNote .'.';
    }

    echo $result;
?>

<!DOCTYPE html>
<html lang="fr">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <h1>Correspondance des notes de musique classiques et américaines</h1>

        <form action="form.php" method="POST" id="notesForm">
            <fieldset>
                <legend>Correspondance classique > américaine</legend>
                <label for="selectNote">Sélectionnez une note : </label>
                <select name="selectNote">
                    <option value="">Choix</option>
                </select>
            </fieldset>
        </form>
</body>
</html>

script.js

(function() {
    var notes = {
        init: function() {
            window.addEventListener('load', function(event) {
                var notationBtn = document.getElementById('notationBtn');
                    notationBtn.style.display = 'block';

                notationBtn.addEventListener('click', function(event) {
                    event.preventDefault();
                    notationBtn.style.display = 'none';

                    var closeBtn = document.createElement('input');
                        closeBtn.type = 'button';
                        closeBtn.id = 'closeBtn';
                        closeBtn.value = 'Close';
                        closeBtn.style.display = 'block';

                    var h1 = document.createElement('h1');
                        h1.textContent = 'Correspondance des notes de musique classiques et américaines';
                    var form = document.createElement('form');
                        form.action = 'form.php';
                        form.id = 'notesForm';
                        form.name = 'notesForm';
                    var fieldset = document.createElement('fieldset');
                    var legend = document.createElement('legend');
                        legend.textContent = 'Correspondance classique > américaine';
                    var label = document.createElement('label');
                        label.htmlFor = 'selectNote';
                        label.textContent = 'Sélectionnez la note : ';
                    var select = document.createElement('select');
                        select.name = 'selectNote';
                    var option = document.createElement('option');
                        option.value = '';
                        option.textContent = 'Choix';
                    var response = document.createElement('p');
                        response.id = 'response';
                    
                    document.body.appendChild(closeBtn);
                    document.body.appendChild(h1);
                    document.body.appendChild(form);
                    form.appendChild(fieldset);
                    fieldset.appendChild(legend);
                    fieldset.appendChild(label);
                    fieldset.appendChild(select);
                    select.appendChild(option);
                    fieldset.appendChild(response);

                    const notesArray = {
                        'C' : 'Do',
                        'D' : 'Ré',
                        'E' : 'Mi',
                        'F' : 'Fa',
                        'G' : 'Sol',
                        'A' : 'La',
                        'B' : 'Si'
                    };

                    const keys = Object.keys(notesArray);

                    keys.forEach((key, index) => {
                        var options = document.createElement('option');
                            options.value = key;
                            options.textContent = notesArray[key];
                        select.appendChild(options);
                    });

                    select.addEventListener('change', function(event) {
                        var httpRequest = new XMLHttpRequest();
                        var url = form.action;
                        var param1 = select.options[this.selectedIndex].value;
                        var param2 = select.options[this.selectedIndex].textContent;
                        httpRequest.open('GET', url+'?usNote='+param1+'&stdNote='+param2, true)
                        httpRequest.addEventListener('readystatechange', function(event) {
                            if (httpRequest.readyState == 4) {
                                if (httpRequest.status == 200) {
                                    response.innerHTML = httpRequest.responseText;
                                } else {
                                    alert('Error code ' + httpRequest.status + ' : ' +httpRequest.statusText);
                                }
                            }
                        });
                        httpRequest.send();
                    });

                    closeBtn.addEventListener('click', function(event) {
                        notationBtn.style.display = 'block';
                        closeBtn.style.display = 'none';
                        h1.style.display = 'none';
                        form.style.display = 'none';
                    });
                });
            });
        }
    };
    notes.init();
})();



Le JS date de juste avant la troisième demande. Quelqu'un saurait-il m'expliquer comment je peux insérer le formulaire de la page PHP vers la page HTML, en passant par Ajax (et sans JQuery) ? Tout ce que je trouve sur internet tourne autour de JQuery, mais je ne peux pas l'utiliser. Je pense savoir que je dois remplacer le code qui génère le formulaire par un appel, mais j'ai essayé de faire un autre appel via XMLHttpRequest, et ça ne donne rien. 

Merci !

  • Partager sur Facebook
  • Partager sur Twitter
19 septembre 2021 à 19:41:03

Bonjour,

As-tu essayé https://developer.mozilla.org/fr/docs/Web/API/Element/innerHTML ?

2/3 petits trucs qui m'intriguent : déclarer une fonction anonyme pour l'appeler juste après, c'est pas fou, autant ne pas mettre de fonction. Et le html, c'est plus facile à faire en html qu'en js.

  • Partager sur Facebook
  • Partager sur Twitter
20 septembre 2021 à 16:38:33

piero5673 a écrit:

Et le html, c'est plus facile à faire en html qu'en js.

Alors, je suis pas à 100% d'accord, là. Bon, en très grande partie oui, mais dans certains cas...
Par exemple moi je me suis déjà servi de javascript pour créer entièrement un tableau ( avec des divs, pas des balises table ) de 64 cases. Et ben coder à la main les huit colonnes contenant chacune 8 cellules, ça doit être un peu long et rébarbatif, alors qu'en js, une petite dizaine de lignes et ça se fait tout seul.
Bon, là, je lis le script.js, effectivement c'est un peu psycho ^^
Ecrire tout ce HTML avec de la manipulation de DOM ? C'est un exercice de style ? C'est histoire de vous montrer que c'est possible ?
Bon, moi je fais beaucoup comme ça, avec du createElement() et du setAttribute(), un coup d'appendChild() et zou!.
Mais effectivement innerHTML, ça permet d'économiser quelques lignes quand même.

Bref, pour tenter de répondre un peu à ta question, quand même, tu devrais plutôt avoir quelque chose comme ça :

<?php
 
    $usNote = $_GET['usNote'];
    $stdNote = $_GET['stdNote'];
 
    if ($usNote === '') {
        $result = 'Aucune note sélectionnée.';
    } else {
        $result = ?>
<fieldset>
...
<option value=""><?php echo $_GET[stdNote']; ?></option>
...
</fieldset> ?>;
echo $result;



et du coup tu modifies ton JS pour que quand il a reçu tout le contenu HTML du formulaire ( éventuellement prérempli comme ici dans la balise <option> ) , il remplace purement et simplement le HTML précédent :

   if(httpRequest.status == 200) {
      document.getElementById('notesForm').innerHTML = httpRequest.responseText;
}



Après, je ne sais pas comment est fait ta formation, peut-être qu'on te montre différentes manières de procéder, pour à la fin te démontrer qu'il y a de meilleures manières que d'autres ?
A mon sens ( et je pense ne pas être le seul à penser comme ça ) la démarche pertinente serait celle-ci :

- Avoir un fichier ( appelons-le index.php, ou même simplement HTML ) dans lequel tu envoies le document complet "par défaut" ( avant toute manipulation par l'utilisateur ).
Il contient ta doctype declaration, ta balise <head> et son contenu habituel ( le lien vers le .css entre autres ), ta balise <body>, le titre, les liens de navigation, un message de bienvenue, du blabla descriptif, ton formulaire "par défaut", et enfin ta balise <script> contenant soit tout le JS, soit un lien vers le fichier .js.

- JS place les eventListeners, comme ici celui qui répond au changement de valeur dans l'input, et envoies une requête AJAX vers un fichier php

- un fichier php qui traite cette requête, et envoie la réponse la plus courte possible. En effet, pourquoi renvoyer l'intégralité du formulaire, qui est déjà sur la page affichée dans le navigateur du client ? Tu consomme de la bande passante inutilement. On t'a probablement parlé du JSON ? Sinon on ne devrait pas tarder, j'imagine. Le principe est de former une chaîne de caractères étant une représentation d'un objet ( la subtile différence entre un JSON et la déclaration d'un objet javascript sont les parenthèses qui entoure les noms des propriétés ).

- Le javascript du client, quand il reçoit sa réponse, traite les données ( un petit JSON.parse(reponse) permet de tranformer le JSON en objet javascript ), et modifie en conséquence les éléments déjà présents dans le document, éventuellement en créé d'autres, etc.

Le but étant de limiter le boulot du serveur ( qui ne construit pas systématiquement TOUTE la page, ou même tout un bout de page, mais uniquement les données demandées ), la taille des informations envoyées ( un JSON plutôt que tout le HTML d'un formulaire, par exemple ), mais aussi le boulot du navigateur client ( même chose, on ne reconstruit pas toute une page ou tout un formulaire, on modifie ou on créé seulement les éléments HTML existant )

-
Edité par LucasWerquin 20 septembre 2021 à 17:19:56

  • Partager sur Facebook
  • Partager sur Twitter
20 septembre 2021 à 17:41:32

Merci à tous les deux pour vos réponses.

piero5673 a écrit:

Bonjour,

As-tu essayé https://developer.mozilla.org/fr/docs/Web/API/Element/innerHTML ?

2/3 petits trucs qui m'intriguent : déclarer une fonction anonyme pour l'appeler juste après, c'est pas fou, autant ne pas mettre de fonction. Et le html, c'est plus facile à faire en html qu'en js.


J'ai effectivement essayé innerHTML. J'ai remplacé toute la partie du script JS qui générait le formulaire par un XMLHTTPRequest, mais je n'ai obtenu aucun résultat. Du coup, je me demande s'il n'est pas possible de mettre deux XMLHTTPRequest dans un même script ?

Pour la fonction anonyme, c'est donné ainsi dans le cours. Apparemment, ça permettrait de rendre le code inaccessible. Pourquoi ne vaut-il mieux pas le mettre ?

LucasWerquin : Désolé j'ai posté avant d'avoir vu l'édition du message.

J'ai l'impression que l'on me montre les méthodes en les découpant par sections. Par exemple juste avant j'ai vu la manipulation du DOM, avant de passer à l'AJAX sur celui-là, probablement au JQuery pour le prochain. Je ne sais pas si ça permet de voir quelles méthodes sont les meilleures ou non, ou même si cette forme d'apprentissage est vraiment pertinente.

En fait, le fait de générer le formulaire par la page PHP est une demande du devoir, l'index.html ne doit être composé que du bouton Notation, le formulaire ne doit pas s'y trouver. Pour résumer :

- Le fichier index.html comporte dans son body un bouton Notation.

- Le fichier form.php comporte le formulaire ainsi que son traitement.

- Le fichier script.js comporte les appels pour insérer le formulaire et la réponse du traitement dans le fichier HTML.

Il ne me semble pas avoir vu passer le JSON dans les cours. Il me permettrait d'atteindre le résultat désiré ?

-
Edité par AlJonathan 20 septembre 2021 à 17:48:02

  • Partager sur Facebook
  • Partager sur Twitter
20 septembre 2021 à 19:57:28

LucasWerquin a écrit:

piero5673 a écrit:

Et le html, c'est plus facile à faire en html qu'en js.

Alors, je suis pas à 100% d'accord, là. Bon, en très grande partie oui, mais dans certains cas...
Par exemple moi je me suis déjà servi de javascript pour créer entièrement un tableau ( avec des divs, pas des balises table ) de 64 cases. Et ben coder à la main les huit colonnes contenant chacune 8 cellules, ça doit être un peu long et rébarbatif, alors qu'en js, une petite dizaine de lignes et ça se fait tout seul.


Effectivement ^^ j'aurais du modérer mes propos.

AlJonathan a écrit:

J'ai effectivement essayé innerHTML. J'ai remplacé toute la partie du script JS qui générait le formulaire par un XMLHTTPRequest, mais je n'ai obtenu aucun résultat. Du coup, je me demande s'il n'est pas possible de mettre deux XMLHTTPRequest dans un même script ?

 Oui, tu peux en mettre une infinité.

AlJonathan a écrit:

Pour la fonction anonyme, c'est donné ainsi dans le cours. Apparemment, ça permettrait de rendre le code inaccessible. Pourquoi ne vaut-il mieux pas le mettre ?

Il faut définir inaccessible, parce que tu peux toujours avoir accès au code js dans un navigateur, et tu peux toujours le copier-coller dans la console. Perso j'aime pas les trucs qui ne servent à rien.

Clairement, le json faciliterais les choses. Je ne sais plus exactement quelles sont les limites de innerHTML. Je crois que ça n'exécute pas le js et qu'il n'aime pas les balise <doctype>, <head>, <body>, <script>. Ca fais un moment que je n'ai pas fait de php, mais il me semble que tu as moyen de renvoyer un morceau d'html, avec juste le formulaire. Je crois que ça marcherais comme ça. 



  • Partager sur Facebook
  • Partager sur Twitter
22 septembre 2021 à 21:15:33

Bonjour,

J'ai repris mon code en testant une autre méthode, et j'arrive désormais à insérer le formulaire généré en PHP sur ma page HTML. Mais je me heurte désormais à un nouveau problème : si je mets un "onchange=submit()" sur mon select, celui-ci me redirige vers la page form.php, même en mettant un preventDefault(). Si je tente un nouvel appel XMLHTTPRequest sur mon select, je reçois ce message d'erreur : script.js:46 Uncaught TypeError: Cannot read properties of null (reading 'addEventListener').

Je mets un lien vers mes codes, il semblerait que je ne puisse pas les poster directement.

Mes codes : https://codepen.io/HeavyFR/pen/rNwrGrR

  • Partager sur Facebook
  • Partager sur Twitter
23 septembre 2021 à 19:22:59

Tu n'as pas d'élément avec un id "notationBtn" dans le DOM, la variable ayant le même nom est nulle, nul ne possède pas la méthode addEventListener.
  • Partager sur Facebook
  • Partager sur Twitter