# Créer une application bancaire Partie 2 : Construire un formulaire de connexion et d'inscription ## Quiz avant le cours [Quiz avant le cours](https://ff-quizzes.netlify.app/web/quiz/43) ### 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, il est nécessaire de disposer d'un mécanisme pour stocker les données personnelles de chaque utilisateur séparément et sélectionner les informations à afficher. Nous ne couvrirons pas la gestion [sécurisée de l'identité utilisateur](https://en.wikipedia.org/wiki/Authentication), car c'est un sujet vaste en soi, mais nous nous assurerons que chaque utilisateur puisse créer un (ou plusieurs) compte(s) bancaire(s) dans notre application. Dans cette partie, nous utiliserons des formulaires HTML pour ajouter des fonctionnalités de connexion et d'inscription à notre application web. Nous verrons comment envoyer les données à une API serveur de manière programmatique, et enfin comment définir des règles de validation de base pour les entrées utilisateur. ### Prérequis Vous devez avoir terminé la partie [Modèles HTML et routage](../1-template-route/README.md) de l'application web pour cette leçon. Vous devez également installer [Node.js](https://nodejs.org) et [exécuter l'API serveur](../api/README.md) localement afin de pouvoir envoyer des données pour créer des comptes. **À noter** Vous aurez deux terminaux à exécuter simultanément comme indiqué ci-dessous : 1. Pour l'application bancaire principale que nous avons construite dans la leçon [Modèles HTML et routage](../1-template-route/README.md) 2. Pour l'[API serveur de l'application bancaire](../api/README.md) que nous venons de configurer ci-dessus. Vous devez avoir ces deux serveurs en fonctionnement pour suivre le reste de la leçon. Ils écoutent sur des ports différents (port `3000` et port `5000`), donc tout devrait fonctionner correctement. Vous pouvez tester si le serveur fonctionne correctement en exécutant cette commande dans un terminal : ```sh curl http://localhost:5000/api # -> should return "Bank API v1.0.0" as a result ``` --- ## Formulaire et contrôles L'élément `
` encapsule une section d'un document HTML où l'utilisateur peut saisir et soumettre des données à l'aide de 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 un champ donné. Remarquez également que le champ pour le `balance` a le type `number`. Cela semble-t-il différent des autres champs ? Essayez d'interagir avec. ✅ Pouvez-vous naviguer et interagir avec les formulaires uniquement à l'aide d'un clavier ? Comment feriez-vous cela ? ## Soumettre des données au serveur Maintenant que nous avons une interface utilisateur fonctionnelle, l'étape suivante consiste à envoyer les données au serveur. Faisons un test rapide avec notre code actuel : que se passe-t-il si vous cliquez sur le bouton *Connexion* ou *Inscription* ? 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 Inscription](../../../../translated_images/click-register.e89a30bf0d4bc9ca867dc537c4cea679a7c26368bd790969082f524fed2355bc.fr.png) L'action par défaut d'un `
` est de soumettre le formulaire à l'URL actuelle du serveur en utilisant la [méthode GET](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.3), en ajoutant directement les données du formulaire à l'URL. Cependant, cette méthode présente quelques inconvénients : - Les données envoyées sont très limitées en taille (environ 2000 caractères). - Les données sont directement visibles dans l'URL (pas idéal pour les mots de passe). - Elle ne fonctionne pas avec les téléchargements de fichiers. C'est pourquoi vous pouvez la 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 les limitations précédentes. > Bien que POST soit 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, par exemple lors de l'implémentation d'un champ de recherche. ### Tâche Ajoutez les propriétés `action` et `method` au formulaire d'inscription : ```html ``` Essayez maintenant de créer un nouveau compte avec votre nom. Après avoir cliqué sur le bouton *Inscription*, vous devriez voir quelque chose comme ceci : ![Fenêtre du navigateur à l'adresse localhost:5000/api/accounts, affichant une chaîne JSON avec les données utilisateur](../../../../translated_images/form-post.61de4ca1b964d91a9e338416e19f218504dd0af5f762fbebabfe7ae80edf885f.fr.png) Si tout se passe bien, le serveur devrait répondre à votre requête avec une réponse [JSON](https://www.json.org/json-en.html) contenant les données du compte créé. ✅ Essayez de vous inscrire à nouveau avec le même nom. Que se passe-t-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 quittons notre application et le navigateur redirige vers l'URL du serveur. Nous essayons d'éviter tous les rechargements de page avec notre application web, car nous créons une [application monopage (SPA)](https://en.wikipedia.org/wiki/Single-page_application). Pour envoyer les données du formulaire au serveur sans forcer un 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. Cela 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 l'attribut `action` du formulaire d'inscription par : ```html ``` Ouvrez `app.js` et 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 du 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 du formulaire sous forme de paires clé/valeur. Ensuite, nous convertissons les données en un objet régulier à l'aide de [`Object.fromEntries()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries) et enfin, nous sérialisons les données en [JSON](https://www.json.org/json-en.html), un format couramment utilisé pour l'échange de 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' }; } } ``` Que fait cette fonction ? Tout d'abord, remarquez le mot-clé `async` ici. Cela signifie que la fonction contient du code qui s'exécutera de manière [**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 courte vidéo sur l'utilisation de `async/await` : [![Async et Await pour gérer les promesses](https://img.youtube.com/vi/YwmlRkrxvkk/0.jpg)](https://youtube.com/watch?v=YwmlRkrxvkk "Async et Await pour gérer les 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 nous remettons `//localhost:5000/api/accounts` ici. - Les paramètres de la requête. C'est là que nous définissons la méthode sur `POST` et fournissons le `body` pour 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` pour que le serveur sache comment interpréter le contenu. Comme le serveur répondra à la requête avec du JSON, nous pouvons utiliser `await response.json()` pour analyser le contenu JSON et renvoyer l'objet résultant. Notez que cette méthode est asynchrone, donc nous utilisons le mot-clé `await` ici avant de retourner pour nous assurer que toutes les erreurs lors de l'analyse sont également capturées. Ajoutez maintenant du code à la fonction `register` pour appeler `createAccount()` : ```js const result = await createAccount(jsonData); ``` Comme nous utilisons le mot-clé `await` ici, nous devons ajouter le mot-clé `async` avant la fonction register : ```js async function register() { ``` Enfin, ajoutons quelques journaux 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 les [outils de développement de votre navigateur](https://developer.mozilla.org/docs/Learn/Common_questions/What_are_browser_developer_tools) et essayez de créer un nouveau compte, vous ne devriez pas voir de changement sur la page web, mais un message apparaîtra dans la console confirmant que tout fonctionne. ![Capture d'écran montrant un message de journal dans la console du navigateur](../../../../translated_images/browser-console.efaf0b51aaaf67782a29e1a0bb32cc063f189b18e894eb5926e02f1abe864ec2.fr.png) ✅ Pensez-vous que les données sont envoyées au serveur de manière sécurisée ? Que se passerait-il si quelqu'un interceptait la requête ? Vous pouvez lire sur [HTTPS](https://en.wikipedia.org/wiki/HTTPS) pour en savoir plus sur la communication sécurisée des données. ## Validation des données Si vous essayez de créer un nouveau compte sans définir un nom d'utilisateur au préalable, vous pouvez voir que le serveur renvoie une erreur avec le code de statut [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 bon de [valider les données du formulaire](https://developer.mozilla.org/docs/Learn/Forms/Form_validation) au préalable lorsque cela est possible, pour s'assurer que vous envoyez une requête valide. Les contrôles de formulaire HTML5 offrent 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éfinissent le nombre minimum et maximum de caractères dans les champs de texte. - `min` et `max` : définissent la valeur minimale et maximale d'un champ numérique. - `type` : définit le type de données attendu, comme `number`, `email`, `file` ou [d'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 modèle [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 en fonction de leur validité en utilisant les pseudo-classes CSS `:valid` et `:invalid`. ### Tâche Il y a 2 champs obligatoires pour créer un compte valide : le nom d'utilisateur et la devise. Les autres champs sont facultatifs. Mettez à jour le HTML du formulaire en utilisant à la fois l'attribut `required` et un texte dans l'étiquette du champ pour indiquer cela : ```html ... ``` Bien que cette implémentation particulière du serveur ne fixe pas de limites spécifiques à la longueur maximale des champs, il est toujours recommandé de définir des limites raisonnables pour toute saisie de texte par l'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](../../../../translated_images/validation-error.8bd23e98d416c22f80076d04829a4bb718e0e550fd622862ef59008ccf0d5dce.fr.png) Une validation comme celle-ci, effectuée *avant* l'envoi de toute donnée 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 une requête au serveur. Une validation supplémentaire effectuée sur le serveur est appelée validation **côté serveur**. En général, les deux doivent être mises en œuvre. Bien que l'utilisation de la validation côté client améliore l'expérience utilisateur en fournissant un retour instantané, la validation côté serveur est essentielle pour garantir que les données utilisateur que vous manipulez sont fiables et sécurisées. --- ## 🚀 Défi Affichez un message d'erreur dans le HTML si l'utilisateur existe déjà. Voici un exemple de ce à quoi la page de connexion finale peut ressembler après un peu de stylisation : ![Capture d'écran de la page de connexion après ajout de styles CSS](../../../../translated_images/result.96ef01f607bf856aa9789078633e94a4f7664d912f235efce2657299becca483.fr.png) ## Quiz post-cours [Quiz post-cours](https://ff-quizzes.netlify.app/web/quiz/44) ## Révision et auto-apprentissage Les développeurs ont fait preuve de beaucoup de créativité dans leurs efforts de création de formulaires, notamment en ce qui concerne les stratégies de validation. Découvrez différents flux de formulaires en explorant [CodePen](https://codepen.com) ; pouvez-vous trouver des formulaires intéressants et inspirants ? ## Devoir [Stylisez votre application bancaire](assignment.md) --- **Avertissement** : Ce document a été traduit à l'aide du service de traduction automatique [Co-op Translator](https://github.com/Azure/co-op-translator). Bien que nous nous efforcions d'assurer l'exactitude, veuillez noter que les traductions automatisées peuvent contenir des erreurs ou des inexactitudes. Le document original dans sa langue d'origine doit être considéré comme la source faisant autorité. Pour des informations critiques, il est recommandé de faire appel à une traduction humaine professionnelle. Nous déclinons toute responsabilité en cas de malentendus ou d'interprétations erronées résultant de l'utilisation de cette traduction.