You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/7-bank-project/3-data/translations/README.fr.md

19 KiB

Créer une application bancaire Partie 3: Méthodes de récupération et d'utilisation des données

Quiz préalable

Quiz préalable

Introduction

Au cœur de chaque application Web, il y a des données. Les données peuvent prendre de nombreuses formes, mais leur objectif principal est toujours d'afficher des informations pour l'utilisateur. Les applications Web devenant de plus en plus interactives et complexes, la manière dont l'utilisateur accède aux informations et interagit avec elles est désormais un élément clé du développement Web.

Dans cette leçon, nous verrons comment récupérer des données d'un serveur de manière asynchrone et utiliser ces données pour afficher des informations sur une page Web sans recharger le code HTML.

Prérequis

Vous devez avoir créé la partie Formulaire de connexion et d'inscription de l'application Web pour cette leçon. Vous devez également installer Node.js et exécuter l'API du serveur localement afin d'obtenir les données de compte.

Vous pouvez tester que le serveur fonctionne correctement en exécutant cette commande dans un terminal:

curl http://localhost:5000/api
# -> devrait renvoyer "Bank API v1.0.0" comme résultat

AJAX et la récupération de données

Les sites Web traditionnels mettent à jour le contenu affiché lorsque lutilisateur sélectionne un lien ou soumet des données à laide dun formulaire, en rechargeant la page HTML complète. Chaque fois que de nouvelles données doivent être chargées, le serveur Web renvoie une toute nouvelle page HTML qui doit être traitée par le navigateur, interrompant laction actuelle de lutilisateur et limitant les interactions pendant le rechargement. Ce flux de travail est également appelé Application multipage ou AMP.

Mettre à jour le flux de travail dans une application multipage

Lorsque les applications Web ont commencé à devenir plus complexes et interactives, une nouvelle technique appelée AJAX (Asynchronous JavaScript and XML) a émergé. Cette technique permet aux applications Web denvoyer et de récupérer des données à partir dun serveur de manière asynchrone à laide de JavaScript, sans avoir à recharger la page HTML, ce qui se traduit par des mises à jour plus rapides et des interactions utilisateur plus fluides. Lorsque de nouvelles données sont reçues du serveur, la page HTML actuelle peut également être mise à jour avec JavaScript à laide de lAPI DOM. Au fil du temps, cette approche a évolué pour devenir ce quon appelle maintenant une Application dune seule page ou SPA.

Mettre à jour le flux de travail dans une application d’une seule page

Lors de lintroduction dAJAX, la seule API disponible pour récupérer des données de manière asynchrone était XMLHttpRequest. Mais les navigateurs modernes implémentent désormais également lAPI Fetch plus pratique et plus puissante, qui utilise des promesses et est mieux adaptée à la manipulation des données JSON.

Bien que tous les navigateurs modernes prennent en charge lAPI Fetch, si vous souhaitez que votre application Web fonctionne sur des navigateurs hérités ou anciens, il est toujours judicieux de vérifier dabord le tableau de compatibilité sur caniuse.com.

Tâche

Dans la leçon précédente nous avons implémenté le formulaire dinscription pour créer un compte. Nous allons maintenant ajouter du code pour vous connecter à laide dun compte existant et récupérer ses données. Ouvrez le fichier app.js et ajoutez une nouvelle fonction login:

async function login() {
  const loginForm = document.getElementById('loginForm')
  const user = loginForm.user.value;
}

Ici, nous commençons par récupérer lélément de formulaire avec getElementById(), puis nous obtenons le nom dutilisateur à partir de lentrée avec loginForm.user.value. Chaque contrôle de formulaire est accessible par son nom (défini dans le code HTML à laide de lattribut name) en tant que propriété du formulaire.

De la même manière que nous avons fait pour lenregistrement, nous allons créer une autre fonction pour effectuer une demande de serveur, mais cette fois pour récupérer les données du compte:

async function getAccount(user) {
  try {
    const response = await fetch('//localhost:5000/api/accounts/' + encodeURIComponent(user));
    return await response.json();
  } catch (error) {
    return { error: error.message || 'Unknown error' };
  }
}

Nous utilisons lAPI fetch pour demander les données de manière asynchrone au serveur, mais cette fois, nous navons pas besoin de paramètres supplémentaires autres que lURL à appeler, car nous ninterrogeons que des données. Par défaut, fetch crée une requête HTTP GET, ce que nous recherchons ici.

encodeURIComponent() est une fonction qui échappe les caractères spéciaux pour URL. Quels problèmes pourrions-nous avoir si nous nappelons pas cette fonction et nutilisons pas directement la valeur user dans lURL?

Mettons maintenant à jour notre fonction login pour utiliser getAccount:

async function login() {
  const loginForm = document.getElementById('loginForm')
  const user = loginForm.user.value;
  const data = await getAccount(user);

  if (data.error) {
    return console.log('loginError', data.error);
  }

  account = data;
  navigate('/dashboard');
}

Tout dabord, comme getAccount est une fonction asynchrone, nous devons la faire correspondre avec le mot-clé await pour attendre le résultat du serveur. Comme pour toute demande de serveur, nous devons également traiter les cas derreur. Pour linstant, nous allons seulement ajouter un message de journal pour afficher lerreur, et y revenir plus tard.

Ensuite, nous devons stocker les données quelque part afin de pouvoir les utiliser plus tard pour afficher les informations du tableau de bord. Étant donné que la variable account nexiste pas encore, nous allons créer une variable globale pour elle en haut de notre fichier:

let account = null;

Une fois les données utilisateur enregistrées dans une variable, nous pouvons naviguer de la page login au dashboard en utilisant la fonction navigate() que nous avons déjà.

Enfin, nous devons appeler notre fonction login lorsque le formulaire de login est soumis, en modifiant le HTML:

<form id="loginForm" action="javascript:login()">

Vérifiez que tout fonctionne correctement en enregistrant un nouveau compte et en essayant de vous connecter à laide du même compte.

Avant de passer à la partie suivante, nous pouvons également compléter la fonction register en ajoutant ceci au bas de la fonction:

account = result;
navigate('/dashboard');

Saviez-vous que par défaut, vous ne pouvez appeler les API du serveur quà partir du même domaine et port que la page Web que vous consultez? Il sagit dun mécanisme de sécurité appliqué par les navigateurs. Mais attendez, notre application web sexécute sur 'localhost:3000' alors que lAPI du serveur sexécute sur localhost:3000, pourquoi cela fonctionne-t-il? En utilisant une technique appelée Cross-Origin Resource Sharing (CORS), il est possible deffectuer des requêtes HTTP inter-origines si le serveur ajoute des en-têtes spéciaux à la réponse, ce qui permet des exceptions pour des domaines spécifiques.

En savoir plus sur les API en suivant cette leçon

Mettre à jour le code HTML pour afficher les données

Maintenant que nous avons les données utilisateur, nous devons mettre à jour le code HTML existant pour lafficher. Nous savons déjà comment récupérer un élément du DOM en utilisant par exemple document.getElementById(). Une fois que vous avez un élément de base, voici quelques API que vous pouvez utiliser pour le modifier ou y ajouter des éléments enfants:

  • En utilisant la propriété textContent, vous pouvez modifier le texte dun élément. Notez que la modification de cette valeur supprime tous les enfants de lélément (le cas échéant) et le remplace par le texte fourni. En tant que tel, cest aussi une méthode efficace pour supprimer tous les enfants dun élément donné en lui attribuant une chaîne vide '' à celui-ci.

  • En utilisant document.createElement() avec la méthode append(), vous pouvez créer et attacher un ou plusieurs nouveaux éléments enfants.

En utilisant la propriété innerHTML dun élément, il est également possible de modifier son contenu HTML, mais celui-ci doit être évité car il est vulnérable aux attaques cross-site scripting (XSS).

Tâche

Avant de passer à lécran du tableau de bord, il y a encore une chose que nous devrions faire sur la page connexion. Actuellement, si vous essayez de vous connecter avec un nom dutilisateur qui nexiste pas, un message saffiche dans la console, mais pour un utilisateur normal, rien ne change et vous ne savez pas ce qui se passe.

Ajoutons un élément despace réservé dans le formulaire de connexion où nous pouvons afficher un message derreur si nécessaire. Un bon endroit serait juste avant la connexion <button>:

...
<div id="loginError"></div>
<button>Login</button>
...

Cet élément <div> est vide, ce qui signifie que rien ne sera affiché à lécran tant que nous ny aurons pas ajouté du contenu. Nous lui donnons également un id afin que nous puissions le récupérer facilement avec JavaScript.

Revenez au fichier app.js et créez une nouvelle fonction dassistance updateElement:

function updateElement(id, text) {
  const element = document.getElementById(id);
  element.textContent = text;
}

Celui-ci est assez simple: selon un élément id et text, il mettra à jour le contenu textuel de lélément DOM avec l'id correspondant. Utilisons cette méthode à la place du message derreur précédent dans la fonction login:

if (data.error) {
  return updateElement('loginError', data.error);
}

Maintenant, si vous essayez de vous connecter avec un compte non valide, vous devriez voir quelque chose comme ceci:

Capture d’écran montrant le message d’erreur affiché lors de la connexion

Maintenant, nous avons un texte derreur qui apparaît visuellement, mais si vous lessayez avec un lecteur décran, vous remarquerez que rien nest annoncé. Pour que le texte ajouté dynamiquement à une page soit annoncé par les lecteurs décran, il devra utiliser quelque chose appelé Live Region. Ici, nous allons utiliser un type spécifique de région en direct (live region) appelée alerte:

<div id="loginError" role="alert"></div>

Implémentez le même comportement pour les erreurs de la fonction register (noubliez pas de mettre à jour le code HTML).

Afficher les informations sur le tableau de bord

En utilisant les mêmes techniques que nous venons de voir, nous nous occuperons également dafficher les informations du compte sur la page du tableau de bord.

Voici à quoi ressemble un objet de compte reçu du serveur:

{
  "user": "test",
  "currency": "$",
  "description": "Test account",
  "balance": 75,
  "transactions": [
    { "id": "1", "date": "2020-10-01", "object": "Pocket money", "amount": 50 },
    { "id": "2", "date": "2020-10-03", "object": "Book", "amount": -10 },
    { "id": "3", "date": "2020-10-04", "object": "Sandwich", "amount": -5 }
  ],
}

Remarque: pour vous faciliter la vie, vous pouvez utiliser le compte test préexistant qui est déjà rempli de données.

Tâche

Commençons par remplacer la section "Balance" dans le code HTML pour ajouter des éléments despace réservé:

<section>
  Balance: <span id="balance"></span><span id="currency"></span>
</section>

Nous ajouterons également une nouvelle section juste en dessous pour afficher la description du compte:

<h2 id="description"></h2>

Étant donné que la description du compte fonctionne comme un titre pour le contenu en dessous, elle est marquée sémantiquement comme un en-tête. Apprenez-en davantage sur limportance de structure de titre pour laccessibilité, et jetez un coup dœil critique à la page pour déterminer ce qui pourrait être un autre titre.

Ensuite, nous allons créer une nouvelle fonction dans app.js pour remplir lespace réservé:

function updateDashboard() {
  if (!account) {
    return navigate('/login');
  }

  updateElement('description', account.description);
  updateElement('balance', account.balance.toFixed(2));
  updateElement('currency', account.currency);
}

Tout dabord, nous vérifions que nous avons les données de compte dont nous avons besoin avant daller plus loin. Ensuite, nous utilisons la fonction updateElement() que nous avons créée précédemment pour mettre à jour le code HTML.

Pour rendre laffichage de la balance plus joli, nous utilisons la méthode toFixed(2) pour forcer laffichage de la valeur avec 2 chiffres après la virgule.

Maintenant, nous devons appeler notre fonction updateDashboard() chaque fois que le tableau de bord est chargé. Si vous avez déjà terminé le devoir de la leçon 1 cela devrait être simple, sinon vous pouvez utiliser limplémentation suivante.

Ajoutez ce code à la fin de la fonction updateRoute():

if (typeof route.init === 'function') {
  route.init();
}

Et mettez à jour la définition des itinéraires avec:

const routes = {
  '/login': { templateId: 'login' },
  '/dashboard': { templateId: 'dashboard', init: updateDashboard }
};

Avec ce changement, chaque fois que la page du tableau de bord est affichée, la fonction updateDashboard() est appelée. Après une connexion, vous devriez alors être en mesure de voir le solde du compte, la devise et la description.

Créer dynamiquement des lignes de tableau avec des modèles HTML

Dans la première leçon nous avons utilisé des modèles HTML avec la méthode appendChild() pour implémenter la navigation dans notre application. Les modèles peuvent également être plus petits et utilisés pour remplir dynamiquement des parties répétitives dune page.

Nous utiliserons une approche similaire pour afficher la liste des transactions dans le tableau HTML.

Tâche

Ajoutez un nouveau modèle dans le code HTML <body>:

<template id="transaction">
  <tr>
    <td></td>
    <td></td>
    <td></td>
  </tr>
</template>

Ce modèle représente une seule ligne de tableau, avec les 3 colonnes que nous voulons remplir: date, object et amount dune transaction.

Ensuite, ajoutez cette propriété id à lélément <tbody> du tableau dans le modèle de tableau de bord pour faciliter la recherche à laide de JavaScript:

<tbody id="transactions"></tbody>

Notre HTML est prêt, passons au code JavaScript et créons une nouvelle fonction createTransactionRow:

function createTransactionRow(transaction) {
  const template = document.getElementById('transaction');
  const transactionRow = template.content.cloneNode(true);
  const tr = transactionRow.querySelector('tr');
  tr.children[0].textContent = transaction.date;
  tr.children[1].textContent = transaction.object;
  tr.children[2].textContent = transaction.amount.toFixed(2);
  return transactionRow;
}

Cette fonction fait exactement ce que ses noms impliquent: en utilisant le modèle que nous avons créé précédemment, elle crée une nouvelle ligne de tableau et remplit son contenu à laide de données de transaction. Nous lutiliserons dans notre fonction updateDashboard() pour remplir la table:

const transactionsRows = document.createDocumentFragment();
for (const transaction of account.transactions) {
  const transactionRow = createTransactionRow(transaction);
  transactionsRows.appendChild(transactionRow);
}
updateElement('transactions', transactionsRows);

Ici, nous utilisons la méthode document.createDocumentFragment() qui crée un nouveau fragment DOM sur lequel nous pouvons travailler, avant de finalement lattacher à notre tableau HTML.

Il reste encore une chose à faire avant que ce code puisse fonctionner, car notre fonction updateElement() ne prend actuellement en charge que le contenu texte. Changeons un peu son code:

function updateElement(id, textOrNode) {
  const element = document.getElementById(id);
  element.textContent = ''; // Removes all children
  element.append(textOrNode);
}

Nous utilisons la méthode append() car elle permet dattacher du texte ou des nœuds DOM à un élément parent, ce qui est parfait pour tous nos cas dutilisation.

Si vous essayez dutiliser le compte test pour vous connecter, vous devriez maintenant voir une liste de transactions sur le tableau de bord 🎉.


🚀 Challenge

Travaillez ensemble pour que la page du tableau de bord ressemble à une véritable application bancaire. Si vous avez déjà stylisé votre application, essayez d'utiliser des requêtes multimédias pour créer un design réactif qui fonctionne bien sur les ordinateurs de bureau et les appareils mobiles.

Voici un exemple de page de tableau de bord stylisée:

Capture d'écran d'un exemple de résultat du tableau de bord après le style

Quiz de validation des connaissances

Quiz de validation des connaissances

Affectation

Refactorisez et commentez votre code