Apparence
Théorie - Semaine 11 - Formulaires avancés et validation
Rappel
Nous avons déjà vu comment faire quelques validations simples avec le JavaScript et le DOM. Maintenant, nous allons amener cela à un autre niveau!
Pourquoi c'est important?
- Prévenir l'envoi de données incorrectes ou incomplètes au serveur
- Améliorer l'expérience utilisateur en fournissant des retours immédiats sur la validité des données, permettant aux utilisateurs de corriger leurs erreurs sans attendre une réponse du serveur.
- Renforcer la sécurité de l'application en empêchant l'injection de données malveillantes.
Page de test
Pour la présente théorie, nous allons utiliser le composant PageConnexion.vue avec le contenu suivant dans le template :
vue
<div class="row">
<form class="mb-3 col-6">
<div>
<label
for="exempleCourriel"
class="form-label"
>Courriel</label>
<input
type="email"
class="form-control"
id="exempleCourriel"
>
</div>
<div>
<label for="exempleMotPasse">Mot de passe</label>
<input
type="password"
class="form-control"
id="exempleMotPasse"
>
</div>
<div class="form-check">
<input
type="checkbox"
class="form-check-input"
id="exempleValidez"
>
<label
class="form-check-label"
for="exempleValidez"
>Validez moi!</label>
</div>
<button
type="submit"
class="btn btn-primary"
>
Soumettre
</button>
</form>
</div>Il s'agit d'un formulaire HTML avec quelques classes bootstrap!
Par contre, aucune liaison entre le code et le formulaire n'est encore faite.
Qu'allons-nous utiliser pour faire les liaisons?
Des variables ref et la directive v-model pour faire les liaisons entre le code et le formulaire.
ce qui devrait nous donner quelque chose comme :
vue
<script setup lang="ts">
import { ref } from 'vue';
const courriel = ref('');
const motDePasse = ref('');
const validezMoi = ref(false);
</script>
<template>
<div class="row">
<form class="mb-3 col-6">
<div>
<label
for="exempleCourriel"
class="form-label"
>Courriel</label>
<input
type="email"
class="form-control"
id="exempleCourriel"
v-model="courriel"
>
</div>
<div>
<label for="exempleMotPasse">Mot de passe</label>
<input
type="password"
class="form-control"
id="exempleMotPasse"
v-model="motDePasse"
>
</div>
<div class="form-check">
<input
type="checkbox"
class="form-check-input"
id="exempleValidez"
v-model="validezMoi"
>
<label
class="form-check-label"
for="exempleValidez"
>Validez moi!</label>
</div>
<button
type="submit"
class="btn btn-primary"
>
Soumettre
</button>
</form>
</div>
</template>À partir d'ici et maintenant, nous allons utiliser une librairie de validation pour faire les validations de notre formulaire. Cela va grandement nous aider à effectuer des validations plus complexes et à gérer les erreurs de manière plus efficace.
Nous allons utiliser vee-validate qui est une librairie de validation très populaire dans l'écosystème Vue.
Installation et utilisation de vee-validate
Installation
Comme à l'habitude, nous allons utiliser npm pour installer la librairie vee-validate ainsi que des règles supplémentaires.
bash
npm install vee-validate @vee-validate/rulesUtilisation
Premièrement, il faut comprendre que vee-validate utilise des composants et des fonctions pour gérer les validations.
À partir de maintenant, nous allons utiliser les composants Form, Field et ErrorMessage au lieu de ceux de base du HTML pour notre formulaire.
Form: Formulaire devee-validate.Field: Champ de formulaire devee-validatequi remplace les champs de formulaire HTML de base.ErrorMessage: Composant qui affiche les messages d'erreur de validation pour un champ donné.
Voici comment nous allons les utiliser dans notre composant PageConnexion.vue :
vue
<script setup lang="ts">
// Importer les composants de vee-validate
import { Form, Field, ErrorMessage } from 'vee-validate';
import { ref } from 'vue';
const courriel = ref('');
const motDePasse = ref('');
const validezMoi = ref(false);
</script>
<template>
<Form class="mb-3 col-6">
<div>
<label
for="exempleCourriel"
class="form-label"
>Courriel</label>
<Field
name="courriel"
type="email"
class="form-control"
id="exempleCourriel"
v-model="courriel"
/>
<ErrorMessage name="courriel" />
</div>
<div>
<label for="exempleMotPasse">Mot de passe</label>
<Field
name="motDePasse"
type="password"
class="form-control"
id="exempleMotPasse"
v-model="motDePasse"
/>
<ErrorMessage name="motDePasse" />
</div>
<div class="form-check">
<Field
name="validezMoi"
type="checkbox"
class="form-check-input"
id="exempleValidez"
v-model="validezMoi"
/>
<label
class="form-check-label"
for="exempleValidez"
>Validez moi!</label>
</div>
<button
type="submit"
class="btn btn-primary"
>
Soumettre
</button>
</Form>
</template>Truc 💡
Il sera primordial de mettre l'attribut name sur les champs de formulaire Field pour que vee-validate puisse faire le lien entre les champs et les règles de validation que nous allons définir par la suite.
Au besoin, vous pouvez vous référer à la documentation officielle de vee-validate pour plus d'informations sur l'utilisation de cette librairie.
Avec l'utilisation de vee-validate, il ne sera plus nécessaire d'utiliser de .preventDefault() pour empêcher l'envoi du formulaire en cas d'erreur de validation. vee-validate gère cela automatiquement pour nous!
Implémentation des règles de validation
Maintenant que notre formulaire possède les champs de formulaire de vee-validate, nous allons implémenter des règles de validation pour chaque champ.
La documentation sur les règles de vee-validate montre les différentes règles de validation disponibles.
Pour que cela soit pris en compte, il faut importer les règles de validation que nous voulons utiliser et les définir dans notre composant.
Nous allons utiliser defineRule pour définir les règles de validation pour chaque champ de notre formulaire. Dans notre composant PageConnexion.vue, nous allons ajouter les règles de validation suivantes :
vue
<script setup lang="ts">
// Importer les règles de validation que nous voulons utiliser
import {defineRule, Field, Form, ErrorMessage} from 'vee-validate';
import {required} from '@vee-validate/rules';
import { ref } from 'vue';
defineRule('required', required);
const courriel = ref('');
const motDePasse = ref('');
const validezMoi = ref(false);
</script>Comment defineRule fonctionne-t-il? Elle va prendre 2 arguments :
- Le nom de la règle telle qu'elle sera utilisée dans votre application
- La fonction de validation à exécuter
On va également devoir définir nos règles. Dans ce cas-ci, il s'agit de la règle required qui vérifie que le champ n'est pas vide.
On doit s'assurer de l'importer avec import {required} from '@vee-validate/rules';
Information ❗
'required'est le nom de la validation telle qu'elle sera utilisée dans le composantrequiredest une fonction. Ici, elle est importée de @vee-validate/rules puisqu'il s'agit d'une validation de base.
Maintenant, il ne restera plus qu'a associer la règle de validation à chaque champ de formulaire en utilisant l'attribut rules sur les champs Field. Par exemple, pour le champ de courriel, nous allons faire :
vue
<Field
name="courriel"
type="email"
class="form-control"
id="exempleCourriel"
v-model="courriel"
rules="required"
/>Information ❗
Si on essaie de soumettre le formulaire sans remplir le champ de courriel, un message d'erreur sera affiché sous le champ de courriel indiquant que ce champ est requis.
Merci vee-validate!
Afficher les messages d'erreur de validation
À l'aide du composant ErrorMessage que nous avons déjà ajouté dans notre formulaire, nous pouvons afficher les messages d'erreur de validation pour chaque champ.
Attention ⚠
RAPPEL! L'attribut name de ErrorMessage doit correspondre à l'attribut name de Field!
Si on essaie de valider le formulaire, le message par défaut courriel is not valid.
Afin de personnaliser le message d'erreur, il sera possible de lui ajouter des classes CSS pour le styliser et de lui donner un message personnalisé. Par exemple :
vue
<ErrorMessage
name="nomClient"
class="text-danger-emphasis small mt-1">
</ErrorMessage>Information ❗
text-danger-emphasisajoute la couleur rouge pâlesmallréduit la taille du textemt-1ajoute une petite marge dans le haut
Afficher les messages d'erreur en français
Il faudra installer le package @vee-validate/i18n pour pouvoir afficher les messages d'erreur en français.
bash
npm install @vee-validate/i18nInformation ❗
Dans votre carrière, vous allez souvent voir I18n. Il s'agit d'un diminutif pour Internationalisation, soit le processus par lequel on internationalise/traduis une application.
Ensuite, il faudra importer les messages d'erreur en français et les définir dans notre composant. Voici comment faire :
vue
<script setup lang="ts">
// Importer les règles de validation que nous voulons utiliser
import {configure, defineRule, Field, Form, ErrorMessage} from 'vee-validate';
import {required} from '@vee-validate/rules';
import { ref } from 'vue';
import {localize, setLocale} from '@vee-validate/i18n';
import fr from '@vee-validate/i18n/dist/locale/fr.json';
defineRule('required', required);
configure({
generateMessage: localize({
fr,
}),
});
setLocale('fr');
const courriel = ref('');
const motDePasse = ref('');
const validezMoi = ref(false);
</script>Information ❗
setLocale('fr') permet de configurer la langue actuelle de l'affichage. Pour importer une autre langue, il suffit de l'importer via une règle d'importation telle que import es from '@vee-validate/i18n/dist/locale/es.json'; et de l'ajouter à l'intérieur du localize({}).
Personnaliser le nom du champ dans les messages d'erreur
- Il faut ajouter la propriété
labelsur le champFieldpour que le message d'erreur puisse utiliser ce nom au lieu du nom du champ. Par exemple :
vue
<Field
name="courriel"
type="email"
class="form-control"
id="exempleCourriel"
v-model="courriel"
rules="required"
label="Courriel"
/>Validation avec plusieurs règles
Il est possible d'ajouter plusieurs règles de validation à un même champ en les séparant par un "pipe" |.
Étape 1 : Définir nos règles :
vue
<script setup lang="ts">
// Importer les règles de validation que nous voulons utiliser
import {configure, defineRule, Field, Form, ErrorMessage} from 'vee-validate';
import {alpha_spaces, required} from '@vee-validate/rules';
import { ref } from 'vue';
import {localize, setLocale} from '@vee-validate/i18n';
import fr from '@vee-validate/i18n/dist/locale/fr.json';
defineRule('required', required);
defineRule('alpha_spaces', alpha_spaces);
configure({
generateMessage: localize({
fr,
}),
});
setLocale('fr');
const courriel = ref('');
const motDePasse = ref('');
const validezMoi = ref(false);
</script>Information ❗
alpha_spaces est une validation de VeeValidate permettant de vérifier que le contenu d'un champ de formulaire contient seulement des lettres et permettant les espaces.
Étape 2 : Ajouter les règles au champ de formulaire :
vue
<Field
name="courriel"
type="email"
class="form-control"
id="exempleCourriel"
v-model="courriel"
rules="required|alpha_spaces"
label="Courriel"
/>Maintenant, si vous entrez des chiffres, un message d'erreur vous indiquera que le courriel ne peut contenir que des lettres!
Validation avec paramètres
Certaines règles de validation peuvent prendre des paramètres pour être plus spécifiques. Par exemple, la règle min qui vérifie que la longueur d'un champ est supérieure ou égale à une certaine valeur prend un paramètre qui indique cette valeur minimale.
Étape 1 : Définir la règle de validation min :
vue
<script setup lang="ts">
// Importer les règles de validation que nous voulons utiliser
import {configure, defineRule, Field, Form, ErrorMessage} from 'vee-validate';
import {alpha_spaces, min, required} from '@vee-validate/rules';
import { ref } from 'vue';
import {localize, setLocale} from '@vee-validate/i18n';
import fr from '@vee-validate/i18n/dist/locale/fr.json';
defineRule('required', required);
defineRule('alpha_spaces', alpha_spaces);
defineRule('min', min);
configure({
generateMessage: localize({
fr,
}),
});
setLocale('fr');
const courriel = ref('');
const motDePasse = ref('');
const validezMoi = ref(false);
</script>Étape 2 : Ajouter la règle au champ de formulaire avec le paramètre :
vue
<Field
name="courriel"
type="email"
class="form-control"
id="exempleCourriel"
v-model="courriel"
rules="required|alpha_spaces|min:5"
label="Courriel"
/>Information ❗
Lorsqu'une validation prend des arguments, on utilise : après le nom de la validation pour préciser les arguments.
Et voilà!
Validation personnalisée
L'attribut rules peut également prendre une fonction de validation personnalisée que vous pouvez définir vous-même. Cette fonction doit retourner true si la validation est réussie ou une chaîne de caractères contenant le message d'erreur si la validation échoue.
Par exemple,
vue
<script setup lang="ts">
// Importer les règles de validation que nous voulons utiliser
import {configure, defineRule, Field, Form, ErrorMessage} from 'vee-validate';
import {alpha_spaces, min, required} from '@vee-validate/rules';
import { ref } from 'vue';
import {localize, setLocale} from '@vee-validate/i18n';
import fr from '@vee-validate/i18n/dist/locale/fr.json';
defineRule('required', required);
defineRule('alpha_spaces', alpha_spaces);
defineRule('min', min);
defineRule('validationPersonnalisee', validationPersonnalisee);
configure({
generateMessage: localize({
fr,
}),
});
setLocale('fr');
const courriel = ref('');
const motDePasse = ref('');
const validezMoi = ref(false);
/**
*
* @param value
*/
function validationPersonnalisee(value: any) {
if (value === 'valeurInvalide') {
return 'Cette valeur est invalide.';
}
return true;
}
</script>Notre champ de formulaire :
vue
<Field
name="courriel"
type="email"
class="form-control"
id="exempleCourriel"
v-model="courriel"
rules="required|alpha_spaces|min:5|validationPersonnalisee"
label="Courriel"
/>Lors de la validation du champ de courriel, si la valeur saisie est valeurInvalide, le message d'erreur personnalisé "Cette valeur est invalide." sera affiché. Pour toute autre valeur qui ne respecte pas les règles précédentes, les messages d'erreur correspondants seront affichés.
Information ❗
Durant le projet final, vous allez devoir travailler avec plusieurs types de Field et plusieurs liaisons v-model. je vous laisse la documentation de vee-validate pour vous aider à faire cela : https://vee-validate.logaretm.com/v4/examples/custom-checkboxes/ (pour les champs de type checkbox).