@knfcz/react-utils
v1.0.0
Published
## Validation de formulaires
Downloads
2
Readme
react-utils
Validation de formulaires
Dans ./formValidation/ se trouvent des fonctions à utiliser pour valider rapidement des formulaires avec react
makeValidator({object} options) => {function} validate
validate({object} validationRules, [{object} state, {function} setState]) => {boolean} formValid
Utilisez makeValidator() en lui filant vos options pour créer votre propre fonction de validation à utiliser dans vos formulaires
Options du validateur:
getErrorMessage: function({string} errorName, {object} errorMessageParameters) => {string} errorMessage
Reçoit le nom et les paramètres d'une règle ayant échoué et renvoie un message d'erreur à afficher dans le formulaire
Configuration du validateur
Dans un fichier à part, exportez la fonction renvoyée par makeValidator()
// validate.js
import { makeValidator } from 'js-utils/formValidation';
const options = {
getErrorMessage: (errorName, errorMessageParameters) =>
translate(`form.validation.errors.${errorName}`, errorMessageParameters),
};
export default makeValidator(options);
Utilisation
Définissez les règles de validation de vos champs dans un objet, des règles prêtes à être utilisées sont dans ./formValidation/rules.js
// UserForm.js
import { rules } from 'js-utils/formValidation';
...
const validationRules = {
firstName: [rules.required(), rules.lengthBetween(2, 20)]
lastName: [rules.required(), rules.lengthBetween(2, 20)]
email: [
rules.required(),
// Vous pouvez passer des options supplémentaires
// en déclarant votre règle dans un objet au format {rule, ...options}
{
rule: rules.isValidEmail(),
getErrorMessage: (errorName, errorMessage) => {
// Si la regle isValidEmail() échoue, cette fonction sera utilisée pour générer le message d'erreur
return "Message d'erreur personnalisé"
}
}]
};
...
Créez le state de votre formulaire en passant un objet contenant les valeurs par defaut de vos champs à createFormInitialState()
// UserForm.js
import { createFormInitialState } from 'js-utils/formValidation';
...
const [formState, setFormState] = useSetState(
createFormInitialState({
firstName: 'Michel',
lastName: 'Smith',
email: '[email protected]',
})
);
...
Puis passez les valeurs et les messages d'erreur de vos champs à vos composants TextInput, etc...
// UserForm.js
...
<TextInput
value={formState.firstName.value}
errorMessage={formState.firstName.error}
...
/>
...
Pour valider le formulaire, vous n'avez qu'a appeler votre fonction validate() crée plus haut, si des champs sont invalides, les messages d'erreurs associés seront enregistrés dans le state et vos composants seront mis à jour
// UserForm.js
import { getFormValues } from 'js-utils/formValidation';
...
const onSubmit = async () => {
if(!validate(validationRules, [formState, setFormState])) {
// Formulaire invalide
return;
}
// Formulaire bueno
// Note: Pour récupérer les données du form dans un objet au format {nomChamp: valeurChamp},
// passez le state de votre formulaire à getFormValues();
await Http.post('https://michel3000.com/users/', getFormValues(formState))
}
...
Créer de nouvelles règles de validation
Les règles de validation reçoivent une valeur à tester et renvoient un tableau au format [nomErreur, parametresMessageErreur], si la valeur est valide, nomErreur devra être false et parametresMessageErreur pourra être omis
Note: Pensez à accepter une valeur vide comme valide, sinon les champs testés avec votre règle ne pourront être laissés vide
Exemple:
export const minLength = min => val => {
if(val !== '' && val.length < min) {
return ['minLength', { min }];
}
return [false];
}
export const minLengthForUsername = minLength(2);
export const minLengthForEmail = minLength(6);
Note: Renvoyer une closure récupérant la valeur à tester en argument permettra aux autre de créer facilement des versions plus spécialisées de vos règles, et rendra la définition des règles de validation plus lisible
Example avec et sans closure
// validation.js
export const validEmail = () => val => {
...
}
export const minLength = (min, val) => {
...
}
export const curriedMinLength = min => val => {
...
}
// SomeForm.js
...
const validationRules = {
email: [validEmail()]
label: [
// Si nous souhaitons passer des arguments autres que la valeur à tester
// à notre règle de validation, nous devrons créer une fonction intermédiaire
// qui recevra la valeur et appelera notre règle en lui passant les arguments supplémentaires
val => minLength(2, val),
// Ce qui est équivalent à
curriedMinLength(2),
]
};
...
Conseils et performance
Par soucis de convention et de rétrocompatibilité (au cas où des arguments seraient ajoutés ultérieurement) les règles de validations ne récupèrent jamais la valeur à tester et doivent renvoyer une closure qui sera appelée avec la valeur en argument, en contrepartie cela peu mener à la création d'un grand nombre de fonctions si vos règles de validation sont souvent regénérées.
// ChristianHipHopGroupAdmissionForm.js
// Ici, chaque appel à getValidationRules() génerera six closures, soit une pour chaque règle,
const getValidationRules = formValues => ({
age: [rules.required(), rules.numberBetween(12, 99)],
name: [rules.required(), rules.numberBetween(12, 99)],
parentName: [rules.requiredIf(formValues.age < 18), rules.lengthBetween(2, 20)],
...
});
Il peut être donc intéressant de créer votre propre fichier de validation dans votre projet, afin d'y créer vos règles et de leur fournir éventuellement des arguments prédéfinis
// src/utils/validation.js
import { rules as defaultRules } from 'js-utils/formValidation';
export const rules = {
...defaultRules,
// Vous pouvez créer required et toutes les autres règles
// ne prenant aucun argument ici une bonne fois pour toutes
required: defaultRules.required(),
validEmail: defaultRules.validEmail(),
// Et facilement créer des règles génériques
validNameLength: defaultRules.lengthBetween(2, 20),
validAge: defaultRules.numberBetween(12, 99),
...
};
...
// ChristianHipHopGroupAdmissionForm.js
import { rules } from 'utils/validation';
// Ici, aucune fonction n'est crée
const getValidationRules = formValues => ({
age: [rules.required, rules.validAge],
name: [rules.required, rules.validNameLength],
parentName: [rules.requiredIf(formValues.age < 18), rules.validNameLength],
...
});
...