:: Enseignements :: ESIPE :: E3INFO :: 2024-2025 :: Programmation Web avec JavaScript ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) |
AJAX, JSON, Fetch, mise à jour du DOM
|
Le but de cet exercice est de fabriquer une application simple qui affiche
un agenda contenant des évènements définis par une date (when),
une occupation (what) et un lieu (where).
Comme pour le TP précédent, on sépare ce que l'on appelle le
modèle (model), les données de l'application et la vue (view),
l'affichage de ces données.
Comme pour les TPs précédents, on vous demande de créer le rapport du TP8 dans un fichier
compte-rendu-tp8.html.
L'application doit pouvoir stocker l'agenda, pour cela nous utiliserons une application backend
écrite en Java
JExpress.java.
Cette application contient à la fois un serveur de fichiers et aussi une API REST
qui permet d'obtenir tous les évènements, d'ajouter un évènement, de supprimer un évènement et
de modifier un évènement.
Pour exécuter le serveur sur la console, vous utiliserez la commande suivante
java --enable-preview JExpress.java
Normalement, une fois que le serveur est lancé, vous n'avez plus besoin de l'arrêter.
Le serveur, est un serveur de test, qui pour permettre de débugger votre application
va attendre 2 secondes avant de traiter les requêtes à l'API pour simuler un serveur
utilisé par plein de clients différents.
Par défaut, le serveur sert tous les fichiers qui sont dans le répertoire dans lequel il est lancé.
Donc pour servir le fichier
agenda.html, les fichiers
JExpress.java
et
agenda.html doivent être dans le même répertoire.
Pour visualiser votre application, le fichier
agenda.html est disponible à l'adresse
http://localhost:8080/agenda.html
Attention (Achtung ! Achtung!): comme l'on a besoin de faire des requêtes AJAX sur les endpoints
du serveur, votre fichier HTML doit
être distribué par le même serveur.
Un navigateur ne vous permettra pas de faire des requêtes AJAX si le fichier HTML est chargé en local
(avec un
file://) sinon vous avez trouvé un bug de sécurité !
L'API REST est définie comme ceci:
-
Obtenir tous les évènements: GET /api/event
Cet appel renvoi l'ensemble des évènements (id, when, what, where) au format JSON
Vous pouvez tester en copiant dans votre navigateur http://localhost:8080/api/event.
-
Ajouter un évènement: POST /api/event
Cet appel prend un paramètre un évènement au format JSON (sans id !) et l'ajoute
à la liste des évènements maintenue par le serveur. Cet appel renvoi 200 suivi de l'évènement
au format JSON (avec l'id qui a été attribué).
-
Supprimer un évènement: DELETE /api/event/id
Avec id, la valeur de l'id de l'évènement que l'on veut supprimer.
Cet appel renvoi un code 200 si cela s'est bien passé ou 404 sinon.
-
Mettre à jour un évènement: PUT /api/event/id
Cet appel prend en paramètre un évènement au format JSON (avec l'id), trouve l'élément
ayant le même id dans la liste et le met à jour.
Cet appel renvoi 200 si l'élément a été mis à jour ou 404 s'il n'existe pas d'élément ayant
l'id indiqué.
Note: c'est un serveur de test, il ne vérifie pas du tout les données que vous allez envoyer.
À vous de faire un peu attention ! Vous pouvez aussi regarder dans l'onglet "NetWork" des WebTool
pour voir si ce que vous envoyez et correcte et si la réponse du serveur est bien celle que vous attendez.
Note2: on peut remarquer que c'est le serveur qui créé les
id et pas votre application Web !
Exercice 1 - Agenda
Le but de cet exercice est d'écrire une petite application Web qui permet de gérer un agenda.
On veut pouvoir, lister les évènements, ajouter un évènement (when, what, where), supprimer un évènement,
mettre à jour un évènement.
Pour cet exercice, nous travaillerons dans le fichier
agenda.html.
Et voici une image qui donne un aperçu de l'interface graphique que l'on veut:
agenda.png
-
Dans un premier temps, on va s'intéresser au code déjà existant dans le fichier agenda.html.
A quoi servent les classes Agenda et Event ?
A quoi servent les fonctions render et replaceView ?
Dans render, la partie qui détaille une carte est spécifiée en utilisant une chaine de caractère,
quelles sont à votre avis les avantages et inconvénients de cette technique par rapport à utiliser
les méthodes document.createElement()/node.appendChild() ?
A quoi sert la ligne e.preventDefault(); ?
-
On veut maintenant afficher les évènements qui sont stockés dans le serveur plutôt que ceux
qui sont en dur dans le code. Supprimer la version en dur dans le code et utiliser
un fetch pour obtenir les évènements auprès du serveur.
Sachant que l'on veut utiliser async/await, comment doit être déclarée la fonction enregistrée
dans le onload ?
Comme on veut découper en fonction pour rendre le code pus clair,
écrire une fonction asynchrone getEvents qui permet
d'obtenir les évènements du serveur.
Puis modifier la fonction onload pour utiliser la fonction asynchrone que vous venez d'écrire.
Note: n'oubliez pas de faire le rafraichissement graphique une fois que les données ont été chargé.
Pourquoi doit-on copier les objets obtenus en parsant le JSON envoyé par le serveur dans des objets Event
plutôt qu'utiliser directement ces objets ?
-
On souhaite maintenant pouvoir supprimer un évènement en utilisant le bouton "Delete".
L'idée est d'envoyer au serveur une requête demandant la suppression de l'évènement
suivie d'une requête re-demandant la liste des évènements.
Écrire la fonction asynchrone deleteEvent puis modifié la fonction flèche
correspondant au click sur le bouton "Delete".
-
Comme le serveur est assez long à répondre, ce n'est pas très satisfaisant pour l'utilisateur,
en effet, on a l'impression que le delete ne marche pas vu qu'il faut attendre.
L'astuce que l'on utilise habituellement consiste à mettre à jour la vue (en supprimant l'évènement)
même si le serveur n'a pas encore répondu, comme cela l'utilisateur à bien la confirmation visuelle
de son action (de la demande de suppression).
Dans le but d'implanter la suppression juste au niveau de la vue, quelle méthode doit-on ajouter
à la classe Agenda ? Implanter cette méthode.
Modifier la fonction flèche correspondant au click du "Delete" pour supprimer l'élément au niveau
de la vue. Bien sûr, on laisse les appels au serveur, car il faut aussi supprimer l'évènement du serveur
et indiquer à l'utilisateur que la donnée a bien été supprimée (ou pas, s'il y a un problème).
Rappel: en JavaScript, on utilise la méthode splice pour supprimer un élément d'un tableau.
-
On souhaite maintenant ajouter l'implantation du bouton "Edit" qui permet de mettre à jour
un évènement (changer le when, what, where).
Sachant que l'on ne peut éditer qu'un seul évènement à la fois,
comment doit-on changer le modèle ?
Sachant que l'on va utiliser le code suivant pour éditer un évènement,
modifier le code pour que lorsque l'on clique sur "Edit", la vue edition
soit affichée.
const editForm = document.createElement("form");
editForm.className = "card-edit-form";
editForm.innerHTML = `
<input type="datetime-local" name="when" value="${event.when}" required>
<input type="text" name="what" value="${event.what}" required>
<input type="text" name="where" value="${event.where}" required>
<div>
<button type="button" class="cancel">Cancel</button>
<button type="submit" class="save">Save</button>
</div>
`;
-
On souhaite implanter les deux boutons "Cancel" et "Save" de la vue d'édition.
"Cancel" abandonne la vue édition. "Save" met à jour l'évènement sur le serveur
et au niveau de l'interface graphique (sans attendre).
Ajouter l'implantation du bouton "Cancel".
Puis ajouter l'implantation du bouton "Save".
-
Enfin, notre interface a un petit problème, on veut éviter que l'on puisse éditer ou
supprimer un évènement si celui-ci a été mis à jour et que la confirmation
du serveur n'est pas encore arrivé. Par contre, on doit pouvoir éditer n'importe
quel autre évènement.
Comment doit-on modifier le modèle ?
Comment doit-on modifier la vue ?
Rappel: désactiver un bouton set fait en ajoutant l'attribut "disabled",
button.setAttribute("disabled", true);.
© Université de Marne-la-Vallée