web-dev-qa-db-fra.com

Meilleure solution JavaScript pour la validation et l'interaction des formulaires côté client?

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.

  • Présentation: Certains champs sont des flottants ou des entiers. La validation signifie supprimer les caractères non décimaux, mais nous voulons également nous assurer que, si un utilisateur entre 5 dans un champ de prix, le champ est mis à jour vers 5.00.
  • Effets secondaires: Certains champs ont des effets secondaires lorsqu'ils sont mis à jour. Par exemple, la mise à jour du prix ou de la quantité d'un article doit mettre à jour un champ de sous-total.
  • Éléments pilotés par widget: Certains champs sont masqués et ont des valeurs remplies par des widgets. Par exemple, un widget de carte vous permet de pointer vers un emplacement et un champ caché est mis à jour avec les coordonnées latitude-longitude, mais l'emplacement doit être dans une certaine région.
  • Groupes: Certains champs sont des groupes, comme l'adresse/la ville/l'état/Zip, et ne doivent être validés que lorsque tous les champs ont été remplis.
  • Validation côté serveur: La validation de certains champs nécessite une vérification principale via les requêtes Ajax
  • Plusieurs formulaires par page: Parfois, un utilisateur doit remplir un formulaire avant qu'une boîte de dialogue s'ouvre avec un autre formulaire. Un framework doit être plus polyvalent que la liaison à 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.)
  • Affichage d'erreur personnalisable: Parfois, des erreurs apparaissent au-dessus des champs, parfois le style de champ change, et nos nouvelles conceptions appellent des popups de type info-bulle (ala qTip ) pour certaines erreurs.
  • Rapidité: L'expérience utilisateur est la clé et le retour tactile est important. Toute solution
  • Boutons Soumettre: Cliquer sur le bouton Soumettre doit tout valider puis afficher une réponse - mais comme une partie de la validation se produit de manière asynchrone.

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.)

52
a paid nerd

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.

  • Présentation : Avec des contraintes de validation personnalisées, vous pouvez lier la validation à l'élément onChange. De plus, comme Regula prend en charge les validateurs personnalisés, vous pouvez demander à votre validateur personnalisé de mettre à jour la valeur d'un champ (modifiez donc 5 à 5.00).
  • Effets secondaires : Regula prend en charge les effets secondaires via des validateurs de contraintes personnalisés.
  • Groupes : Regula prend en charge les groupes de validation. Vous pouvez cibler des groupes spécifiques pour la validation. En combinant un validateur personnalisé et un groupe, vous pouvez contrôler le comportement du validateur afin qu'il valide seulement lorsque tous les éléments de ce groupe sont remplis (vous devrez effectuer cette vérification via Javascript normal bien que).
  • Validation côté serveur : Avec les contraintes personnalisées, vous pouvez effectuer un appel AJAX pour effectuer la validation côté serveur. Compte tenu de la structure actuelle du framework, il doit nécessairement s'agir d'un appel ajax bloquant. Je prévois d'ajouter une fonctionnalité asynchrone à l'avenir.
  • Plusieurs formulaires par page : Regula ne se limite pas à valider un formulaire par page. Il peut gérer plusieurs formulaires (je ne sais pas si j'ai bien compris votre demande - donc je n'ai peut-être pas répondu correctement à cette partie).
  • Affichage d'erreur personnalisable: Regula ne fait rien à l'interface utilisateur de la page en ce qui concerne la validation. Lorsque vous validez, vous obtenez un ensemble de violations de contraintes qui contiennent des messages d'erreur et autres. C'est à vous de voir comment les afficher.
  • Snappiness: Je n'ai effectué aucun benchmark, je ne peux donc pas commenter les performances de mon framework à cet égard.
  • Boutons de soumission: C'est quelque chose que je n'ai pas encore résolu (asynchrone vs synchrone).

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).

55
Vivin Paliath

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é!

13
Mitch Malone

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.

8
Tracker1

Parsley.js semble être un choix agréable et populaire au moment de la rédaction (août 2013).

5
Simone

Répondre moi-même car quelqu'un de notre équipe a remarqué Validateur de jQuery Tools!

  • Présentation - Prend en charge les champs de saisie HTML5. Les champs pattern garantissent que l'utilisateur ne peut saisir le test que dans un certain modèle.
  • Effets secondaires - Déclenche des événements sur le formulaire et sur les champs individuels: onFail et onSuccess
  • Éléments pilotés par widget - Les "types d'entrée personnalisés" sont encouragés. La démo de base comprend même un champ "âge" vieux de nombres naturels.
  • Groupes - Ecrivez un "fonction matcher" dont le seul but est de filtrer les champs à valider.
  • Validation côté serveur - Le fait et le fait intelligemment - dépend de votre validateur appelant un rappel (donc il est compatible avec l'async) au lieu d'une valeur de retour.
  • Plusieurs formulaires par page - jQuery Tools semble être très bien construit et cela ne devrait pas être un problème.
  • Affichage d'erreur personnalisable - Des erreurs à côté des champs? Tout en un seul endroit? Aucun problème. Pas encore assez bon? Lier les événements en cas d'échec. Utilise même les info-bulles par défaut.
  • Snappiness - Les démos sont très accrocheuses
  • Boutons de soumission - Pas de problème.

Mise à jour: Oui, juste réimplémenté une partie de notre site avec les info-bulles de validation de jQuery Tools. Fantastique!

2
a paid nerd

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.

1
Fenton
 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;
}
0
Sushant Patil

Allez avec les plugins de validation jQuery. Ça ne m'a jamais fait défaut jusqu'à présent

0
Hello Universe