Ajax avec jQuery et JSON (deuxième partie)

Dans la première partie de notre tutoriel, nous avons effectué une requête Ajax de la façon la plus simple qui soit, mais de nombreuses améliorations pourraient être apportées à notre script. En particulier : dès qu’il y a soumission de formulaire, il faut systématiquement vérifier les valeurs avant de les traiter. En effet, que se passerait-il si l’utilisateur, au lieu d’entrer deux nombres décimaux, entrait un mot ? Non seulement le serveur ne devra pas effectuer un quelconque traitement, mais en plus, il lui faudra retourner les erreurs rencontrées. Et côté client, il va nous falloir afficher ces erreurs. Et tout ceci, bien sûr, toujours sans aucun rechargement de page, puisque c’est le principe même d’Ajax.

Notre validation va donc consister à vérifier que les valeurs renseignées dans les champs A et B par l’utilisateur sont bien des nombres décimaux. Ceci peut être fait entièrement en javascript (sans requête au serveur), mais comme chacun sait, une validation serveur est toujours indispensable, car c’est la seule garantie face aux utilisateurs qui auraient désactivé javascript.

Voici à quoi ressemblera notre page, si l’utilisateur fait une erreur de saisie :

https://www.webmaster-hub.com/publications/IMG/jpg/screen.jpg

controleur.php

Nous allons donc commencer par vérifier les valeurs dans notre script controleur.php. Pour vérifier qu’une valeur est bien un nombre décimal, voici l’expression régulière à utiliser :

preg_match('/^-?[0-9]+(.[0-9]+)?$/', $x)

Cette expression renverra true si $x est un nombre décimal (exemple : 19.5) , false sinon. Notez également que les nombres négatifs seront autorisés.

Dans notre contrôleur, nous allons donc instancier un tableau $erreurs, puis nous allons contrôler chacun des deux champs et, en cas d’erreur, on empilera un message d’erreur dans le tableau $errors. Ce qui nous donne donc le bout de code suivant :

$errors = array();
if(!preg_match('/^-?[0-9]+(.[0-9]+)?$/', $nombre_a))
      $errors[] = "La valeur a n'est pas un nombre décimal.";
if(!preg_match('/^-?[0-9]+(.[0-9]+)?$/', $nombre_b))
      $errors[] = "La valeur b n'est pas un nombre décimal.";

Maintenant, le serveur va pouvoir effectuer une action différente, selon que les champs étaient corrects ou non. Pour savoir s’il y a des erreurs, il suffit tout simplement de compter le nombre d’éléments du tableau $errors. Si ce nombre est nul, c’est qu’il n’y a pas d’erreur. Dans le cas contraire, c’est qu’il y a au moins une erreur :

if(count($errors)==0) { // Il n'y a pas d'erreur : on traite le formulaire }
else { // Il y a des erreurs : on va retourner les erreurs au client }

Dans les deux cas, nous créerons un tableau $reponse. Ce tableau contiendra avant une première paire clé/valeur, indiquant si oui ou non l’opération a réussi. Choisissons par exemple d’appeler notre clé « ok » : elle prendra la valeur 1 en cas de réussite, 0 en cas d’échec. Complétons donc notre petit bout de code :

if(count($errors)==0) { // Il n'y a pas d'erreur : on traite le formulaire 
     $reponse = array( 'ok' => 1 ); }
else { // Il y a des erreurs : on va retourner les erreurs au client
     $reponse = array( 'ok' => 0 ); }

Maintenant, dans le premier cas (réussite), nous enregistrerons dans le tableau les deux résultats de l’addition et de la multiplication. Ce qui nous donne :

if(count($errors)==0) { // Il n'y a pas d'erreur : on traite le formulaire
     $resultat_addition = $nombre_a + $nombre_b;
     $resultat_multiplication = $nombre_a * $nombre_b;
     $reponse = array( 'ok' => 1, 'resultat_addition' => $resultat_addition, 'resultat_multiplication' => $resultat_multiplication ); 
}

Et dans le deuxième cas (échec), nous enregistrerons dans le tableau les messages d’erreurs, qui ont déjà été réunies dans le tableau $errors, ce qui nous donne donc :

} else {  // Il y a des erreurs
$reponse = array( 'ok' => 0, 'messages_erreurs' => $errors ); }

Pour terminer, tout à la fin de notre script, nous écrirons le tableau encodé en JSON :

print(json_encode($reponse));

Voici donc le code complet de controleur.php :

<?PHP
if(isset($_REQUEST['action'])) {
switch($_REQUEST['action']) {
case 'calculer' :
//----------------------------------------------------------
// Récupération des valeurs
$nombre_a = trim($_REQUEST['nombre_a']);
$nombre_b = trim($_REQUEST['nombre_b']);
//----------------------------------------------------------
// Validation
$errors = array();
if(!preg_match('/^\-?[0-9]+(\.[0-9]+)?$/', $nombre_a))
$errors[] = "La valeur a n'est pas un nombre décimal.";
if(!preg_match('/^\-?[0-9]+(\.[0-9]+)?$/', $nombre_b))
$errors[] = "La valeur b n'est pas un nombre décimal.";
if(count($errors)==0) {
//------------------------------------------------------
// Il n'y a pas d'erreur
$resultat_addition = $nombre_a + $nombre_b;
$resultat_multiplication = $nombre_a * $nombre_b;
$reponse = array(
'ok' => 1,
'resultat_addition' => $resultat_addition,
'resultat_multiplication' => $resultat_multiplication
);
} else {
//------------------------------------------------------
// Il y a des erreurs
$reponse = array(
'ok' => 0,
'messages_erreurs' => $errors
);
}
//------------------------------------------------------
// Ecriture de la réponse
print(json_encode($reponse));
break;
}
}
?>

calcul.php

Passons maintenant au côté client, c’est à dire à l’affichage des éventuelles erreurs et des éventuels résultats. La première chose à faire est de créer une balise div vide dans notre code html : cette balise vide servira à recueillir les éventuels messages d’erreur. Concrètement : si notre code javascript, après son appel Ajax, reçoit des messages d’erreur de la part du serveur, javascript inserrera ces messages sous la forme d’une liste dans notre balise créée à cet effet.

Plaçons donc une div vide, ayant pour identifiant « messages_erreurs », dans notre code html, c’est à dire dans notre fichier calcul.php, par exemple juste avant le formulaire :

<div id="messages_erreurs" style="color:red;"></div>

Vous remarquerez au passage qu’on applique la couleur rouge aux futurs contenus de cette div. En effet, il est habituel d’écrire les messages d’erreur en rouge. Evidemment, l’idéal serait plus propre de définir cette propriété dans une feuille de style externe.

Nous n’avons rien d’autre à faire du côté du HTML. Désormais, tout va se passer du côté du javascript. Reprenons donc notre fichier calcul.js, et plus particulièrement notre fonction de traitement de la réponse serveur : function(data).

calcul.js

Pour rappel : le tableau data est exactement identique au tableau $reponse que nous a retourné php. Ce tableau data contient donc notre fameuse variable ok, dont la valeur nous indique si le traitement a réussi ou non. Nous aurons donc :

function(data) {
    var ok = data['ok'];
        if(ok==1) {
            // Succès
            // On va écrire les résultats des opérations 
        }
        else {
           // Echec
           // On va afficher les messages d'erreur
       }       
}

Dans le premier cas (succès), rien de plus simple : nous l’avons déjà fait dans la première partie de ce tutoriel. Il suffit de remplir les champs prévus pour recueillir les résultats de l’addition et de la multiplication, résultats qui sont contenus dans notre tableau data :

if(ok==1) {
       // Succès
       $("input#resultat_addition").val(data['resultat_addition']); 
       $("input#resultat_multiplication").val(data['resultat_multiplication']);
}

Dans le deuxième cas (échec), nous allons afficher les messages d’erreur. Commençons par les récupérer dans notre tableau data :

var messages_erreurs = data[‘messages_erreurs’] ;

Etant donné qu’il peut y en avoir plusieurs, nous les afficherons sous la forme d’une liste ul li. Commençons donc par créer notre liste ul, à l’intérieur de la balise « messages_erreurs » que nous avons créée tout à l’heure dans le html :

$('#messages_erreurs').append('<ul>')

Et maintenant, nous effectuons une boucle sur les messages d’erreur, et les ajoutons sous la forme d’éléments de liste dans notre balise ul :

for(var i in messages_erreurs) {
    $('#messages_erreurs ul').append('<li>'+messages_erreurs[i]+'</li>'); 
}

Maintenant si vous effectuez un petit test : tout fonctionne. Si vous remplissez les champs a et b avec des valeurs décimales, vous constaterez que tout fonctionne comme prévu : les résultats de l’addition et de la multiplication sont correctement calculés et affichés. Et si vous tapez n’importe quoi (par exemple un mot) au lieu de nombres décimaux, des messages d’erreur s’afficheront.

Mais il reste encore un problème : les messages d’erreur ne disparaissent jamais. Si l’utilisateur se trompe une seule fois : les messages d’erreur ainsi générés resteront affichés sur la page. Voila pourquoi, systématiquement, quand il soumet le formulaire, nous devons commencer par vider cette liste. Pour vider une balise, il suffit d’utiliser la fonction empty() de jQuery sur cette balise. Nous effectuerons donc cette opération au tout début du traitement de la soumission du formulaire par javascript :

$("form#formulaire_calcul").submit(function() { 
      $('#messages_erreurs').empty(); // ...

Voici donc le code complet de notre fichier calcul.js :

$(document).ready(function() { 
     $("form#formulaire_calcul").submit(function() { 
          $('#messages_erreurs').empty(); 
          $.getJSON("controleur.php", {
               "action" : "calculer", 
               "nombre_a" : $("input#nombre_a").val(), 
               "nombre_b" : $("input#nombre_b").val() }, 
               function(data) { 
                     var ok = data['ok']; 
                     if(ok==1) { 
                          // Succès 
                          $("input#resultat_addition").val(data['resultat_addition']); 
                          $("input#resultat_multiplication").val(data['resultat_multiplication']); 
                    } else { 
                          // Echec 
                          var messages_erreurs = data['messages_erreurs']; 
                          $('#messages_erreurs').append('<ul>'); 
                          for(var i in messages_erreurs) { 
                              $('#messages_erreurs').append('<li>'+messages_erreurs[i]+'</li>'); 
                          } 
                    } 
              } 
        ); return false; 
   });   
});

Voila, notre formulaire est désormais fonctionnel. Mais beaucoup de choses pourraient encore être améliorées. Par exemple : que se passe-t-il si javascript est désactivé ? En l’état actuel : rien du tout, ce qui est un peu dommage. Il nous faudrait donc améliorer notre script de manière à rendre ce formulaire fonctionnel y compris quand javascript est désactivé, et ceci avec un minimum de modifications à notre code. Ce sera l’objet d’une troisième partie.