# Créer une application bancaire Partie 2: Créer un formulaire de connexion et d'inscription ## Quiz préalable [Quiz préalable](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/43?loc=fr) ### Introduction Dans presque toutes les applications Web modernes, vous pouvez créer un compte pour avoir votre propre espace privé. Comme plusieurs utilisateurs peuvent accéder à une application Web en même temps, vous avez besoin d'un mécanisme pour stocker les données personnelles de chaque utilisateur séparément et sélectionner les informations à afficher. Nous n'expliquerons pas comment gérer [l'identité de l'utilisateur en toute sécurité](https://en.wikipedia.org/wiki/Authentication) car il s'agit d'un sujet étendu en soi, mais nous veillerons à ce que chaque utilisateur puisse créer un (ou plusieurs) compte bancaire sur notre application. Dans cette partie, nous utiliserons des formulaires HTML pour ajouter une connexion et une inscription à notre application Web. Nous verrons comment envoyer les données à une API serveur par programmation, et finalement comment définir des règles de validation de base pour les entrées utilisateur. ### Prérequis Vous devez avoir terminé les [modèles HTML et routage](../../1-template-route/translations/README.fr.md) d'une application Web pour cette leçon. Vous devez également installer [Node.js](https://nodejs.org/fr) et [exécuter l'API du serveur](../../api/translations/README.fr.md) localement afin de pouvoir envoyer des données pour créer des comptes. **Prenez note** Vous aurez deux terminaux fonctionnant en même temps comme indiqué ci-dessous. 1. Pour l'application bancaire principale, nous avons intégré la leçon [Modèles HTML et routage](../../1-template-route/translations/README.fr.md) 2. Pour l'[API du serveur Bank APP](../../api/translations/README.fr.md), que nous avons configuré ci-dessus. Vous avez besoin que les deux serveurs soient opérationnels pour suivre le reste de la leçon. Ils écoutent sur différents ports (port `3000` et port `5000`) donc tout devrait bien fonctionner. Vous pouvez tester que le serveur fonctionne correctement en exécutant cette commande dans un terminal : ```sh curl http://localhost:5000/api # -> devrait renvoyer "Bank API v1.0.0" comme résultat ``` --- ## Formulaire et contrôles L'élément `
` encapsule une section d'un document HTML où l'utilisateur peut saisir et soumettre des données avec des contrôles interactifs. Il existe toutes sortes de contrôles d'interface utilisateur (UI) qui peuvent être utilisés dans un formulaire, les plus courants étant les éléments `` et `
``` En utilisant l'attribut `value`, nous pouvons définir une valeur par défaut pour une entrée donnée. Notez également que l'entrée pour `balance` a le type `number`. Est-ce que ça a l'air différent des autres entrées ? Essayez d'interagir avec lui. ✅ Pouvez-vous naviguer et interagir avec les formulaires en utilisant uniquement un clavier ? Comment feriez-vous cela? ## Soumission des données au serveur Maintenant que nous avons une interface utilisateur fonctionnelle, la prochaine étape consiste à envoyer les données à notre serveur. Faisons un test rapide avec notre code actuel : que se passe-t-il si vous cliquez sur le bouton *Connexion* ou *S'inscrire* ? Avez-vous remarqué le changement dans la section URL de votre navigateur ? ![Capture d'écran du changement d'URL du navigateur après avoir cliqué sur le bouton S'inscrire](../images/click-register.png) L'action par défaut pour un `
` consiste à soumettre le formulaire à l'URL du serveur actuel à l'aide de la [méthode GET](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.3 ), en ajoutant les données du formulaire directement à l'URL. Cette méthode a cependant quelques défauts : - Les données envoyées sont de taille très limitée (environ 2000 caractères) - Les données sont directement visibles dans l'URL (pas génial pour les mots de passe) - Cela ne fonctionne pas avec les téléchargements de fichiers C'est pourquoi vous pouvez le modifier pour utiliser la [méthode POST](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5) qui envoie les données du formulaire au serveur dans le corps de la requête HTTP, sans aucune des limitations précédentes. > Alors que POST est la méthode la plus couramment utilisée pour envoyer des données, [dans certains scénarios spécifiques](https://www.w3.org/2001/tag/doc/whenToUseGet.html) il est préférable d'utiliser la méthode GET, lorsque l'on implémente un champ de recherche par exemple. ### Tâche Ajoutez les propriétés `action` et `method` au formulaire d'inscription : ```html ``` Essayez maintenant d'enregistrer un nouveau compte avec votre nom. Après avoir cliqué sur le bouton *S'inscrire*, vous devriez voir quelque chose comme ceci : ![Une fenêtre de navigateur à l'adresse localhost:5000/api/accounts, affichant une chaîne JSON avec des données utilisateur](../images/form-post.png) Si tout se passe bien, le serveur doit répondre à votre demande avec une réponse [JSON](https://www.json.org/json-fr.html) contenant les données de compte qui ont été créées. ✅ Essayez de vous enregistrer à nouveau avec le même nom. Que se produit'il? ## Soumettre des données sans recharger la page Comme vous l'avez probablement remarqué, il y a un léger problème avec l'approche que nous venons d'utiliser : lors de la soumission du formulaire, nous sortons de notre application et le navigateur redirige vers l'URL du serveur. Nous essayons d'éviter tous les rechargements de pages avec notre application Web, car nous créons une [Application à page unique (SPA)](https://en.wikipedia.org/wiki/Single-page_application). Pour envoyer les données du formulaire au serveur sans forcer le rechargement de la page, nous devons utiliser du code JavaScript. Au lieu de mettre une URL dans la propriété `action` d'un élément ``, vous pouvez utiliser n'importe quel code JavaScript précédé de la chaîne `javascript:` pour effectuer une action personnalisée. L'utiliser signifie également que vous devrez implémenter certaines tâches qui étaient auparavant effectuées automatiquement par le navigateur : - Récupérer les données du formulaire - Convertir et encoder les données du formulaire dans un format approprié - Créer la requête HTTP et l'envoyer au serveur ### Tâche Remplacez le formulaire d'inscription `action` par : ```html ``` Ouvrez `app.js` ajoutez une nouvelle fonction nommée `register` : ```js function register() { const registerForm = document.getElementById('registerForm'); const formData = new FormData(registerForm); const data = Object.fromEntries(formData); const jsonData = JSON.stringify(data); } ``` Ici, nous récupérons l'élément de formulaire à l'aide de `getElementById()` et utilisons l'assistant [`FormData`](https://developer.mozilla.org/docs/Web/API/FormData) pour extraire les valeurs des contrôles de formulaire en tant qu'ensemble de paires clé/valeur. Ensuite, nous convertissons les données en un objet normal à l'aide de [`Object.fromEntries()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries) et enfin sérialisons les données en [JSON](https://www.json.org/json-fr.html), un format couramment utilisé pour échanger des données sur le Web. Les données sont maintenant prêtes à être envoyées au serveur. Créez une nouvelle fonction nommée `createAccount` : ```js async function createAccount(account) { try { const response = await fetch('//localhost:5000/api/accounts', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: account }); return await response.json(); } catch (error) { return { error: error.message || 'Unknown error' }; } } ``` A quoi sert cette fonction ? Tout d'abord, notez le mot-clé `async` ici. Cela signifie que la fonction contient du code qui s'exécutera [**asynchrone**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function). Lorsqu'il est utilisé avec le mot-clé `await`, il permet d'attendre l'exécution du code asynchrone - comme attendre la réponse du serveur ici - avant de continuer. Voici une vidéo rapide sur l'utilisation de `async/await` : [![Async et Await pour la gestion des promesses](https://img.youtube.com/vi/YwmlRkrxvkk/0.jpg)](https://youtube.com/watch?v=YwmlRkrxvkk "Async et Await pour la gestion des promesses") > 🎥 Cliquez sur l'image ci-dessus pour une vidéo sur async/await. Nous utilisons l'API `fetch()` pour envoyer des données JSON au serveur. Cette méthode prend 2 paramètres : - L'URL du serveur, donc on remet `//localhost:5000/api/accounts` à ce niveau. - Les paramètres de la requête. C'est là que nous définissons la méthode sur `POST` et fournissons le `body` de la requête. Comme nous envoyons des données JSON au serveur, nous devons également définir l'en-tête `Content-Type` sur `application/json` afin que le serveur sache comment interpréter le contenu. Comme le serveur répondra à la demande avec JSON, nous pouvons utiliser `wait response.json()` pour analyser le contenu JSON et renvoyer l'objet résultant. Notez que cette méthode est asynchrone, nous utilisons donc le mot-clé `await` ici avant de revenir pour nous assurer que toutes les erreurs lors de l'analyse sont également détectées. Ajoutez maintenant du code à la fonction `register` pour appeler `createAccount()`: ```js const result = await createAccount(jsonData); ``` Comme nous utilisons ici le mot-clé `await`, nous devons ajouter le mot-clé `async` avant la fonction register: ```js async function register() { ``` Enfin, ajoutons quelques logs pour vérifier le résultat. La fonction finale devrait ressembler à ceci: ```js async function register() { const registerForm = document.getElementById('registerForm'); const formData = new FormData(registerForm); const jsonData = JSON.stringify(Object.fromEntries(formData)); const result = await createAccount(jsonData); if (result.error) { return console.log('An error occurred:', result.error); } console.log('Account created!', result); } ``` C'était un peu long mais nous y sommes arrivés ! Si vous ouvrez vos [outils de développement de navigateur](https://developer.mozilla.org/docs/Learn/Common_questions/What_are_browser_developer_tools) et essayez d'enregistrer un nouveau compte, vous ne devriez voir aucun changement sur la page Web, mais un message s'affichera. apparaissent dans la console confirmant que tout fonctionne. ![Capture d'écran montrant le message de journal dans la console du navigateur](../images/browser-console.png) ✅ Pensez-vous que les données sont envoyées au serveur en toute sécurité ? Et si quelqu'un était capable d'intercepter la demande ? Vous pouvez en savoir plus sur [HTTPS](https://fr.wikipedia.org/wiki/HTTPS) pour en savoir plus sur la communication de données sécurisée. ## La validation des données Si vous essayez d'enregistrer un nouveau compte sans définir de nom d'utilisateur au préalable, vous pouvez voir que le serveur renvoie une erreur avec le code d'état [400 (Bad Request)](https://developer.mozilla.org/docs/Web/HTTP/Status/400#:~:text=The%20HyperText%20Transfer%20Protocol%20(HTTP,%2C%20or%20deceptive%20request%20routing).). Avant d'envoyer des données à un serveur, il est recommandé de [valider les données du formulaire](https://developer.mozilla.org/docs/Learn/Forms/Form_validation) au préalable lorsque cela est possible, pour vous assurer d'envoyer une demande valide. Les contrôles de formulaires HTML5 fournissent une validation intégrée à l'aide de divers attributs : - `required` : le champ doit être rempli sinon le formulaire ne peut pas être soumis. - `minlength` et `maxlength` : définit le nombre minimum et maximum de caractères dans les champs de texte. - `min` et `max` : définit la valeur minimum et maximum d'un champ numérique. - `type` : définit le type de données attendu, comme `numéro`, `e-mail`, `fichier` ou [autres types intégrés](https://developer.mozilla.org/docs/Web/HTML/Element/input). Cet attribut peut également modifier le rendu visuel du contrôle de formulaire. - `pattern` : permet de définir un pattern d'[expression régulière](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Regular_Expressions) pour tester si les données saisies sont valides ou non. > Astuce : vous pouvez personnaliser l'apparence de vos contrôles de formulaire selon qu'ils sont valides ou non en utilisant les pseudo-classes CSS `:valid` et `:invalid`. ### Tâche Il y a 2 champs obligatoires pour créer un nouveau compte valide, le nom d'utilisateur et la devise, les autres champs étant facultatifs. Mettez à jour le code HTML du formulaire, en utilisant à la fois l'attribut `required` et le texte du libellé du champ: ```html ... ``` Bien que cette implémentation de serveur particulière n'impose pas de limites spécifiques sur la longueur maximale des champs, il est toujours recommandé de définir des limites raisonnables pour toute entrée de texte utilisateur. Ajoutez un attribut `maxlength` aux champs de texte : ```html ... ... ``` Maintenant, si vous appuyez sur le bouton *S'inscrire* et qu'un champ ne respecte pas une règle de validation que nous avons définie, vous devriez voir quelque chose comme ceci : ![Capture d'écran montrant l'erreur de validation lors de la tentative de soumission du formulaire](../images/validation-error.png) Une validation comme celle-ci effectuée *avant* l'envoi de données au serveur est appelée validation **côté client**. Mais notez qu'il n'est pas toujours possible d'effectuer toutes les vérifications sans envoyer les données. Par exemple, nous ne pouvons pas vérifier ici si un compte existe déjà avec le même nom d'utilisateur sans envoyer de requête au serveur. Une validation supplémentaire effectuée sur le serveur est appelée validation **côté serveur**. Généralement, les deux doivent être implémentés, et bien que l'utilisation de la validation côté client améliore l'expérience utilisateur en fournissant un retour instantané à l'utilisateur, la validation côté serveur est cruciale pour s'assurer que les données utilisateur que vous manipulez sont saines et sûres. --- ## 🚀 Challenge Afficher un message d'erreur dans le code HTML si l'utilisateur existe déjà. Voici un exemple de ce à quoi peut ressembler la page de connexion finale après un peu de style : ![Capture d'écran de la page de connexion après l'ajout de styles CSS](../images/result.png) ## Quiz de validation des connaissances [Quiz de validation des connaissances](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/44?loc=fr) ## Révision et étude personnelle Les développeurs sont devenus très créatifs dans leurs efforts de création de formulaires, en particulier en ce qui concerne les stratégies de validation. Découvrez les différents flux de formulaires en parcourant [CodePen](https://codepen.com); pouvez-vous trouver des formulaires intéressants et inspirants ? ## Affectation [Concevez votre application bancaire](assignment.fr.md)