Nos formulaires Web sont vraiment complexes. Quelle est une excellente solution pour la validation de formulaire extensible, de préférence une qui fonctionne avec jQuery?
Contexte:
Notre site a un peu d'Ajax, mais l'accent est mis sur l'expérience utilisateur à travers une vingtaine de formulaires multipages ou "assistants". Ces formulaires sont compliqués.
5
dans un champ de prix, le champ est mis à jour vers 5.00
.onSubmit
- nous publions parfois plusieurs formulaires dans l'ordre depuis la même page en utilisant Ajax. (Par exemple, nous permettons aux utilisateurs de s'inscrire et de créer un widget d'un seul coup, mais, en raison des systèmes hérités, ce flux nécessite deux POST.)Nous utilisons actuellement la bibliothèque jQuery Validation mais nos formulaires semblent dépasser ses capacités. J'ai regardé des choses comme <angular /> , Knockout et Backbone.js , mais je crains qu'elles ne le soient aussi lourds ou qu'ils nous obligeraient à réécrire notre frontend.
(Cela devrait être un wiki communautaire.)
Il s'agit d'un plug sans vergogne, mais pourrais-je proposer un framework que j'ai conçu? Je l'ai construit sur la base d'annotations (comme le validateur Hibernate). Il prend en charge les contraintes personnalisées et je pense qu'il est assez puissant. Ici est aussi une question Stackoverflow où j'ai demandé une révision du framework.
5
à 5.00
).Voici quelques exemples:
Voici une validation standard, avec des contraintes intégrées:
<input id = "myInput"
name = "myInput"
type = "text"
class = "regula-validation"
data-constraints = '@NotEmpty @IsNumeric @Between(min=1, max=5)' />
jQuery(document).ready(function() {
// must call regula.binnd() first. The best place would be in an
// onload handler. This function looks for elements with
// a class name of "regula-validation" and binds the
// appropriate constraints to the elements
regula.bind();
jQuery("#myForm").submit(function() {
// this function performs the actual validation
var validationResults = regula.validate();
for(var index in validationResults) {
var validationResult = validationResults[index];
alert(validationResult.message);
}
});
});
Comme vous pouvez le voir, vous ne travaillez qu'avec des violations de contraintes, et la manière dont vous affichez le message d'erreur dépend donc entièrement de vous.
Voici un exemple de contrainte personnalisée:
regula.custom({
name: "MustBe42",
defaultMessage: "The answer must be equal to 42",
validator: function() {
return this.value == 42;
}
});
Et son utilisation:
<input id = "theAnswerToLifeTheUniverseAndEverything"
name = "theAnswerToLifeTheUniverseAndEverything"
value = ""
class = "regula-validation"
data-constraints = "@MustBe42" />
Étant donné que le validateur est une fonction Javascript, vous pouvez le faire faire n'importe quoi (donc cela répond à votre question sur les effets secondaires).
Voici un exemple d'une autre contrainte qui accepte des paramètres:
regula.custom({
name: "DivisibleBy",
defaultMessage: "{label} must be divisible by {divisor}",
params: ["divisor"],
validator: function(params) {
var divisor = params["divisor"];
return (this.value % divisor) == 0;
}
});
Et l'utilisation:
<input id = "number"
name = "number"
value = ""
class = "regula-validation"
data-constraints = "@DivisibleBy(divisor=3, label='The Number')" />
Voici un exemple d'utilisation de groupes de validation:
<input id = "score"
name = "score"
type = "text"
class = "regula-validation"
data-constraints = '@IsNumeric(label="Score",
message="{label} needs to be a number!"
groups=[FirstGroup, SecondGroup, ThirdGroup]' />
<input id = "age"
name = "age"
type = "text"
class = "regula-validation"
data-constraints = '@IsNumeric(label="Age",
message="{label} needs to be a number!"
groups=[SecondGroup]' />
<input id = "name"
name = "name"
type = "text"
class = "regula-validation"
data-constraints = '@NotEmpty(label="Name",
message="{label} cannot be empty!"
groups=[FirstGroup]' />
Et un extrait qui ne valide que FirstGroup
(donc seuls score
et name
sont validés):
var constraintViolations = regula.validate({groups: [regula.Group.FirstGroup]});
var messages = "";
for(var index in constraintViolations) {
var constraintViolation = constraintViolations[index];
messages += constraintViolation.message + "\n";
}
if(messages != "") {
alert(messages);
}
Si vous prévoyez de l'essayer, je vous recommande de télécharger la version 1.1.1 . La documentation actuelle correspond spécifiquement à cette version. Dans 1.2.1 j'ai ajouté la prise en charge des contraintes composées, mais je n'ai pas mis à jour ma documentation pour refléter cela.
Je comprends si cela ne répond pas à toutes vos préoccupations ou si ce n'est pas ce que vous recherchez. Je pensais que je le mettrais juste là-bas. De plus, si vous le vérifiez, je m'assurerai de mettre à jour la documentation pour refléter la version 1.2.1 . J'ai été occupé à l'école et au travail et je n'ai donc pas eu le temps de le faire.
MISE À JOUR # 1
Sohnee a mentionné la validation côté client. Je travaille actuellement sur une intégration entre Regula et Spring 3. J'espère que je devrais être en mesure de le publier très bientôt (en fonction à nouveau du travail et de l'école). L'intégration fonctionne en traduisant les contraintes de validation Hibernate en contraintes de validation Regula. De cette façon, vous n'avez à écrire le code de validation qu'une seule fois (principalement). Cependant, pour les contraintes personnalisées, vous devrez toujours écrire du code du côté Javascript (le validateur personnalisé). Mais une fois que vous avez annoté du code côté serveur avec les contraintes de validation Hibernate, vous n'avez rien à faire du côté client; ces contraintes sont automatiquement appliquées aux éléments de formulaire côté client.
Matthew Abbott a également pu intégrer Regula avec ASP.NET MVC .
MISE À JOUR # 2
J'ai une webapp de démonstration (mavenisée) sur github qui présente l'intégration entre Regula et Spring 3.0.x Web MVC en utilisant Hibernate Validator. Ce n'est pas vraiment documenté ou quoi que ce soit, c'est plus une preuve de concept. J'ai l'intention d'ajouter de la documentation à la page github sur l'intégration et comment cela fonctionne.
MISE À JOUR # 3
J'ai mis à jour la documentation sur le wiki , et cela correspond maintenant à la dernière version, 1.2.2 (j'ai fait un petit bug, c'est pourquoi c'est 1.2.2 maintenant).
J'ai utilisé cela jQuery formValidator plusieurs fois en conjonction avec tout un tas d'environnements différents. J'espère que cela aide, car j'ai rarement passé plus d'une heure à le configurer.
À votre santé!
Je dirais que le plugin jQuery Validation fait un bon travail. Je l'ai combiné avec le plugin metadata pour passer les paramètres de validation côté serveur au client. J'ai également intégré quelques points clés à tous les formulaires afin de pouvoir utiliser un modèle commun pour la validation et quelques états exceptionnels/personnalisés. Cela inclut un message d'alerte personnalisé et un affichage.
Il ne fait pas tout ce que vous voulez, mais c'est la meilleure option et le meilleur comportement par défaut que j'ai vu. Encore une fois, j'utilise les métadonnées (attribut "data-meta") avec. Et il peut être plié à votre gré. J'utilise également des métadonnées pour la liaison de contrôle aux éléments d'entrée côté client. Cela sépare ma logique côté client de celle côté serveur, mais plus facile à long terme pour essayer d'injecter js à partir de la logique côté serveur.
Parsley.js semble être un choix agréable et populaire au moment de la rédaction (août 2013).
Répondre moi-même car quelqu'un de notre équipe a remarqué Validateur de jQuery Tools!
pattern
garantissent que l'utilisateur ne peut saisir le test que dans un certain modèle.onFail
et onSuccess
Mise à jour: Oui, juste réimplémenté une partie de notre site avec les info-bulles de validation de jQuery Tools. Fantastique!
Roches de validation côté serveur.
Fournissez les résultats d'une telle validation via une demande AJAX si vous le souhaitez ... ou utilisez un framework côté serveur qui ajoutera également une validation côté client - mais ne l'écrivez pas deux fois.
function isEmpty(text) {
if(text == undefined) {
return true;
}
if(text.replace(/\s+/g, ' ').length == 0) {
return true;
}
return false;
}
function isValidBoolean(text) {
if(text == undefined || (text.toLowerCase() != "true" && text.toLowerCase() != "false")) {
return false;
}
return true;
}
function isValidDouble(text) {
var out = parseFloat(text);
if(isNaN(out)) {
return false;
}
return true;
}
function isValidLong(text) {
var out = parseInt(text);
if(isNaN(out)) {
return false;
}
return true;
}
function isValidDate(text) {
if(Date.parseString(text, 'MM/dd/yyyy HH:mm:ss') == null) {
return false;
}
return true;
}
function hasDuplicates(array) {
var valuesSoFar = {};
for (var i = 0; i < array.length; ++i) {
var value = array[i];
if (Object.prototype.hasOwnProperty.call(valuesSoFar, value)) {
return true;
}
valuesSoFar[value] = true;
}
return false;
}
Allez avec les plugins de validation jQuery. Ça ne m'a jamais fait défaut jusqu'à présent