Mise en place d’une API RESTful CRUD – Côté Client
Dans ce second article de notre série, nous allons explorer la création de l’interface utilisateur pour interagir avec l’API RESTful que nous avons développée précédemment. Nous nous concentrerons sur la mise en place de l’HTML et de JavaScript nécessaires pour effectuer des opérations CRUD sur nos tâches de manière fluide et intuitive.
Maintenant que notre serveur est prêt à répondre aux différentes requêtes via l’API, il est temps de créer l’interface utilisateur. Nous commencerons par structurer la page HTML de base, qui accueillera notre application. Ensuite, nous y ajouterons les actions JavaScript pour interagir avec l’API et permettre la gestion des tâches en temps réel.
Page HTML de base
Pour commencer, le squelette HTML de l’application doit être mis en place. Il faut également lier les fichiers de bibliothèque nécessaires, notamment Bootstrap pour le style. Voici la mise en place du fichier index.php
.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<title>Gestion des Tâches</title>
</head>
<body>
<div class="container">
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script>
// Les scripts JavaScript viendront ici
</script>
</body>
</html>
Ajout des Éléments de Commande et de Conteneurs
Nous avons structuré l’interface utilisateur en utilisant Bootstrap pour créer une carte contenant les champs de saisie. Cette structure est essentielle pour une bonne expérience utilisateur, car elle permet une interaction simple et efficace avec l’API. Cette carte comprend un en-tête indiquant l’action à réaliser, suivi de champs permettant de saisir le titre, la description, la date limite, et la priorité d’une tâche. Un bouton permet d’ajouter ou de modifier une tâche. La liste des tâches s’affiche en dessous de la carte, chaque tâche étant présentée sous forme d’élément de liste.
<div class="container">
<h1 class="mt-5">Gestion des Tâches</h1>
<div class="card mb-3" id="taskInputCard">
<div class="card-header">
<h5 id="taskCardTitle">Ajouter une Tâche</h5>
</div>
<div class="card-body">
<input type="text" id="taskTitle" class="form-control" placeholder="Titre de la tâche">
<input type="text" id="taskDescription" class="form-control mt-2" placeholder="Description de la tâche">
<input type="date" id="taskDeadline" class="form-control mt-2">
<select id="taskPriority" class="form-control mt-2">
<option value="low">Basse</option>
<option value="medium">Moyenne</option>
<option value="high">Haute</option>
</select>
<button id="addTaskBtn" class="btn btn-primary mt-2">Ajouter Tâche</button>
</div>
</div>
<h2>Tâches</h2>
<ul id="taskList" class="list-group">
</ul>
</div>
Implémentation des Scripts JavaScript pour le CRUD
Dans ce chapitre, nous allons intégrer les scripts JavaScript nécessaires pour permettre les opérations CRUD (Créer, Lire, Mettre à jour, Supprimer) sur nos tâches. Grâce à l’utilisation de l’API que nous avons mise en place, nous allons rendre l’interface interactive. Les utilisateurs pourront ainsi ajouter de nouvelles tâches, consulter celles déjà existantes, modifier les informations d’une tâche et supprimer celles qui ne sont plus nécessaires. Cette fonctionnalité est essentielle pour une gestion efficace des tâches au sein de notre application.
Focalisons tour à tour sur chaque opération CRUD pour en explorer le fonctionnement.
1. Récupération des Tâches (GET)
Ajoutons une fonction pour récupérer les tâches depuis l’API. Cette fonction effectuera une requête GET à notre endpoint, récupérera les données en format JSON et les affichera sur l’interface utilisateur.
endpoint
Un endpoint est une URL ou un point d’accès dans une API où des demandes (requests) peuvent être envoyées pour interagir avec les ressources du serveur. Chaque endpoint correspond généralement à une opération spécifique, comme récupérer des données, en ajouter, les mettre à jour ou les supprimer. En résumé, c’est le point de contact entre le client et le serveur pour échanger des informations.
Voici comment procéder :
async function getTasks() {
const response = await fetch('https://example.com/api.php');
// Pensez à pointer vers votre propre URL
const tasks = await response.json();
displayTasks(tasks);
}
2. Affichage des Tâches
Nous allons également créer la fonction qui est invoquée, par la fonction getTasks
, afin d’afficher les tâches récupérées. Dans un premier temps, assurons nous que le conteneur de réception soit vide, puis vérifions s’il y a ou pas des taches à afficher:
function displayTasks(tasks) {
taskList.innerHTML = '';
if (tasks.length === 0) {
// Aucune tâche à afficher
} else {
// Afficher la liste des tâches
}
}
Lorsque la liste des tâches est vide, il est essentiel d’informer l’utilisateur de manière claire et concise. Dans ce cas, un nouvel élément de liste (li
) est créé pour indiquer qu’il n’y a pas de tâches à afficher. En attribuant à cet élément la classe list-group-item
, il s’intègre visuellement dans la structure de la liste, tout en affichant le message « Aucune tâche à afficher. » Cela permet à l’utilisateur de comprendre facilement que la liste est actuellement vide, offrant ainsi une meilleure expérience utilisateur et une interface plus intuitive.
const li = document.createElement('li');
li.className = 'list-group-item';
li.textContent = 'Aucune tâche à afficher.';
taskList.appendChild(li);
Lorsque des tâches sont présentes, nous allons les parcourir à l’aide d’une boucle. Chaque tâche sera affichée dans une liste, présentant l’ensemble des informations qui la caractérisent. Cela permettra à l’utilisateur d’avoir une vue d’ensemble claire de toutes les tâches en cours.
tasks.forEach(task => {
const li = document.createElement('li');
li.className = 'list-group-item d-flex justify-content-between align-items-center';
li.innerHTML = `
<div>
<strong>${task.title}</strong>
<p>${task.description}</p>
<small>Créée le: ${new Date(task.created_at).toLocaleString()}</small><br>
<small>Modifiée le: ${new Date(task.updated_at).toLocaleString()}</small>
</div>
<!-- Ajouter les boutons de Modification et de Suppression -->
`;
taskList.appendChild(li);
});
Il nous restera ensuite à intégrer les boutons de modification et de suppression pour chaque tâche. Ces fonctionnalités seront ajoutées dans une section ultérieure, permettant ainsi à l’utilisateur de gérer ses tâches de manière complète et intuitive.
3. Ajout d’une Tâche (POST)
La fonction responsable de l’ajout d’une nouvelle tâche à l’API est essentielle pour notre application. Elle permettra à l’utilisateur de créer des tâches directement depuis l’interface, en saisissant les détails requis tels que le titre, la description, la date limite et la priorité. En appelant cette fonction, nous garantissons que les informations de la tâche seront correctement envoyées au serveur et enregistrées dans notre base de données. Voici comment cette fonction est mise en place
async function addTask() {
const response = await fetch('<a href="https://example.com/api.php">https://example.com/api.php</a>', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: taskTitle.value,
description: taskDescription.value,
due_date: taskDeadline.value, // change 'deadline' to 'due_date'
priority: 'low' // par exemple, vous pouvez définir une priorité par défaut
})
});
const result = await response.json();
alert(result.message);
taskTitle.value = '';
taskDescription.value = '';
taskDeadline.value = '';
getTasks();
}
Ce fragment de code est conçu pour envoyer une requête à l’API afin d’ajouter une nouvelle tâche. Tout d’abord, il utilise la méthode fetch
pour effectuer une requête HTTP de type POST vers l’URL de l’API. Les en-têtes de la requête indiquent que le contenu envoyé est au format JSON, ce qui est essentiel pour que le serveur puisse correctement interpréter les données fournies.
Dans le corps de la requête, un objet JSON est créé, contenant les informations relatives à la tâche à ajouter : le title
, la description
, la due_date
, et la priority
, cette dernière étant par défaut fixée à « low ». Une fois la requête envoyée, le code attend la réponse du serveur grâce à await response.json()
, permettant ainsi de récupérer et de convertir la réponse en format JSON.
Après cela, un message d’alerte est affiché à l’utilisateur pour l’informer du résultat de l’opération, qu’elle soit réussie ou non. Pour faciliter une nouvelle saisie, les champs de saisie sont ensuite réinitialisés, permettant à l’utilisateur de commencer avec un formulaire vide. Enfin, la fonction getTasks()
est appelée pour actualiser la liste des tâches affichées, intégrant ainsi la nouvelle tâche dans l’interface utilisateur.
Afin de parfaire la fonctionnalité d’ajout d’une nouvelle tâche, il est important de s’assurer que la requête n’est envoyée que si un titre et une date d’échéance ont été définis. Pour cela rien de plus simple, il suffit de s’assurer que ces données ne sont pas nulles.
Ajoutons juste au départ de la fonction cette vérification:
async function addTask() {
if (!taskTitle.value.trim() || !taskDeadline.value) {
alert("Veuillez remplir tous les champs obligatoires.");
return; // Sortir de la fonction si la validation échoue
}
// Le reste du code déjà présent dans la fonction
}
4. Ajout de la Fonction d’édition d’une tâche
Dans ce chapitre, nous allons implémenter la fonctionnalité d’édition des tâches. Nous commencerons par ajouter un bouton « Modifier » à chaque tâche affichée dans la liste. Ce bouton, lorsqu’il est cliqué, appellera la fonction editTask
, permettant de pré-remplir les champs de saisie avec les informations de la tâche sélectionnée.
Ensuite, nous activerons un bouton « Annuler » pour permettre à l’utilisateur de revenir à l’état précédent sans apporter de modifications. Nous ajusterons également le texte du bouton principal pour qu’il change en fonction de l’action (créer ou modifier) et mettrons à jour son listener en conséquence.
Enfin, pour améliorer l’expérience utilisateur, nous appliquerons une mise en surbrillance sur la fiche de tâche pendant l’édition, signalant ainsi clairement à l’utilisateur qu’il est en mode modification.
Ajout du fragment HTML
<div>
<button class="btn btn-warning btn-sm" onclick="editTask(${task.id}, '${task.title}', '${task.description}', '${task.due_date}')">Modifier</button>
</div>
Ce fragment de code crée un bouton « Modifier » pour chaque tâche dans la liste. En utilisant la classe Bootstrap btn-warning
, le bouton est stylisé pour être visible et attirer l’attention. L’attribut onclick
appelle la fonction editTask
, en lui passant les informations nécessaires de la tâche correspondante, telles que l’ID, le titre, la description et la date d’échéance. Cela permet à l’utilisateur de déclencher l’édition de la tâche en un clic, facilitant ainsi la gestion des tâches.
Ajout de la fonction editTask()
function editTask(id, title, description, due_date) {
taskTitle.value = title;
taskDescription.value = description;
taskDeadline.value = due_date;
// espace réservé pour ajouter la classe de surbrillance à la carte
addTaskBtn.textContent = 'Mettre à jour la tâche';
const cancelButton = document.createElement('button');
cancelButton.textContent = 'Annuler';
cancelButton.className = 'btn btn-secondary btn-sm ml-2';
cancelButton.onclick = cancelEdit;
addTaskBtn.parentNode.appendChild(cancelButton);
addTaskBtn.removeEventListener('click', addTask);
addTaskBtn.onclick = () => {
updateTask(id);
cancelButton.remove(); // Supprimer le bouton Annuler après la mise à jour
};
}
Pour parfaire l’ergonomie, lorsque l’utilisateur passe en mode de modification, nous pouvons ajouter une classe qui va modifier l’apparence visuelle de la carte. Deux actions sont nécessaires, d’abord ajouter le style dans l’entête du document, et ensuite compléter le code JavaScript dans la fonction editTask()
.
<style>
.highlight-card {
background-color: #ffeeba; /* Couleur de surbrillance proche du bouton warning */
}
</style>
// Ajoutez la classe de surbrillance à la carte
document.getElementById('taskInputCard').classList.add('highlight-card');
document.getElementById('taskCardTitle').textContent = 'Modifier la Tâche';
Il nous faut maintenant prendre en charge les deux fonctions appelées, l’une par le bouton de modification updateTask()
que nous verrons au prochain chapitre, l’autre par le bouton d’annulation cancelEdit()
.
function cancelEdit() {
taskTitle.value = '';
taskDescription.value = '';
taskDeadline.value = '';
// Retirer la classe de surbrillance de la carte
document.getElementById('taskInputCard').classList.remove('highlight-card');
document.getElementById('taskCardTitle').textContent = 'Ajouter une Tâche';
addTaskBtn.textContent = 'Ajouter Tâche';
addTaskBtn.addEventListener('click', addTask);
const cancelButton = document.querySelector('button.btn-secondary');
if (cancelButton) {
cancelButton.remove();
}
}
La fonction cancelEdit
permet de réinitialiser l’interface utilisateur lorsque l’utilisateur choisit d’annuler l’édition d’une tâche. Elle commence par vider les champs de saisie pour garantir qu’aucune donnée résiduelle ne soit présente. Ensuite, elle retire la classe de surbrillance de la carte d’entrée, ce qui restaure son apparence originale. Le titre de la carte est également rétabli à « Ajouter une Tâche ». De plus, le texte du bouton d’action est changé en « Ajouter Tâche », et l’écouteur d’événement pour l’ajout de tâche est réactivé. Enfin, si le bouton « Annuler » est présent, il est supprimé de l’interface, permettant ainsi de revenir à un état d’entrée propre et intuitif.
5. Prise en charge de la modification
Une fois la fiche de tâche modifiée, l’utilisateur peut cliquer sur le bouton « Mettre à jour la tâche ». Ce clic invoque la fonction updateTask
, qui se charge d’envoyer les nouvelles données de la tâche modifiée à l’API pour qu’elles soient enregistrées dans la base de données, mettant ainsi à jour la tâche existante.
async function updateTask(id) {
const response = await fetch('<a href="https://example.com/api.php">https://example.com/api.php</a>', {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: id,
title: taskTitle.value,
description: taskDescription.value,
due_date: taskDeadline.value,
status: 'pending', // ou le statut actuel
priority: 'low' // ou la priorité actuelle
})
});
const result = await response.json();
alert(result.message);
}
Ce fragment de code correspond à la fonction updateTask
, qui envoie une requête HTTP de type PUT
à l’API pour mettre à jour une tâche spécifique. Elle inclut les nouvelles valeurs de la tâche, telles que le titre, la description, la date d’échéance, et d’autres propriétés comme le statut et la priorité. La réponse de l’API est ensuite récupérée et un message de confirmation est affiché à l’utilisateur pour indiquer que la tâche a été mise à jour avec succès.
À l’instar de la fonction addTask
, il est essentiel d’ajouter un contrôle de validation pour s’assurer que tous les champs obligatoires (comme le titre et la date) soient bien remplis avant de procéder à la mise à jour. Une fois la tâche mise à jour avec succès, les champs de saisie doivent être vidés pour permettre une nouvelle entrée, et la fonction getTasks
doit être invoquée afin de rafraîchir la liste des tâches affichées et refléter la mise à jour en temps réel.
async function updateTask(id) {
if (!taskTitle.value.trim() || !taskDeadline.value) {
alert("Veuillez remplir tous les champs obligatoires.");
return; // Sortir de la fonction si la validation échoue
}
// Code déjà présent dans la fonction
// Réinitialisez le formulaire
taskTitle.value = '';
taskDescription.value = '';
taskDeadline.value = '';
addTaskBtn.textContent = 'Ajouter Tâche';
addTaskBtn.onclick = addTask; // Remettez la fonction d'ajout d'origine
getTasks(); // Rafraîchir la liste des tâches
}
6. Suppression d’une Tâche (DELETE)
Avant de pouvoir utiliser la fonction de suppression dans notre application, nous devons ajouter un bouton « Supprimer » pour chaque tâche affichée dans la liste. Ce bouton va appeler la fonction deleteTask
en lui transmettant l’identifiant de la tâche concernée. Voici le fragment de code HTML à insérer :
<div>
<!-- Bouton de Modification déjà présent -->
<button class="btn btn-danger btn-sm" onclick="deleteTask(${task.id})">Supprimer</button>
</div>
Une fois ce bouton ajouté pour chaque tâche, la fonction JavaScript deleteTask
pourra être invoquée, permettant de supprimer une tâche de la liste.
Cette fonction deleteTask
prend en paramètre l’identifiant (id
) de la tâche à supprimer. Elle envoie une requête HTTP de type DELETE
à l’API, en incluant l’ID de la tâche dans le corps de la requête, au format JSON. Le serveur est alors censé supprimer la tâche correspondante.
async function deleteTask(id) {
const response = await fetch('https://example.com/api.php', {
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ id })
});
const result = await response.json();
alert(result.message); // Affiche le message de confirmation de suppression
getTasks(); // Rafraîchit la liste des tâches après suppression
}
Une fois la réponse du serveur reçue, elle est convertie en JSON, et un message de confirmation est affiché à l’utilisateur. Enfin, la fonction getTasks
est appelée pour actualiser l’affichage des tâches restantes après la suppression.
7. Initialisation des Événements
Finalement, nous devons attacher les événements aux éléments de l’interface afin de rendre l’application pleinement interactive. Le bouton pour ajouter une tâche (addTaskBtn
) est relié à la fonction addTask
, tandis que la fonction getTasks()
est appelée immédiatement pour récupérer et afficher la liste des tâches existantes dès le chargement de la page :
addTaskBtn.addEventListener('click', addTask);
getTasks(); // Appel initial pour récupérer les tâches
Cette structure assure une interaction fluide avec l’API REST. L’interface utilisateur devient intuitive, permettant aux utilisateurs d’ajouter, afficher et supprimer des tâches sans recharger la page, comme dans une application de type SPA (Single Page Application). De plus, la structure mise en place est évolutive, laissant la possibilité d’ajouter facilement des fonctionnalités futures comme la mise à jour des tâches ou l’ajout de catégories.
Ces opérations CRUD forment le cœur de notre application, permettant aux utilisateurs de gérer leurs tâches en temps réel.
Conclusion
La création d’une interface utilisateur réactive et intuitive est tout aussi importante que la mise en place de l’API elle-même. En suivant les étapes présentées dans cet article, vous pouvez construire une application complète de gestion de tâches. N’hésitez pas à approfondir vos connaissances sur REST et JavaScript pour enrichir vos futurs projets.
Pour approfondir votre compréhension des concepts REST, vous pouvez consulter notre article « Comprendre le concept de REST pour développer efficacement ses applications ». Ce dernier vous fournira des bases solides pour mieux saisir les interactions entre le client et le serveur.