jquery.validate.unobtrusive ne fonctionne pas avec les éléments injectés dynamics

Je travaille avec ASP.Net MVC3 , le moyen le plus simple d’utiliser la validation client serait d’activer jquery.validate.unobtrusive . Tout fonctionne bien, pour les choses qui viennent directement du serveur.

Mais quand j’essaie d’injecter de nouvelles “entrées” avec JavaScript, et je savais que je devais appeler $.validator.unobtrusive.parse() pour relier les validations. Mais encore, tous ces champs injectés dynamics ne fonctionnent pas.

Pire encore, j’essaie de lier manuellement en utilisant jquery.validate et cela ne fonctionne pas non plus. Des pensées?

    J’ai créé une extension pour la bibliothèque jquery.validate.unobtrusive qui a résolu ce problème pour ma situation – cela pourrait être intéressant.

    http://xhalent.wordpress.com/2011/01/24/applying-unobtrusive-validation-to-dynamic-content/

    J’ai essayé l’approche de Xhalent mais malheureusement cela ne fonctionnait pas pour moi. L’approche de Robin a fonctionné et n’a pas fonctionné. Cela fonctionnait très bien pour les éléments ajoutés dynamicment, mais si vous essayiez d’utiliser JQuery pour supprimer tous les atsortingbuts de validation et les étendues du DOM, la bibliothèque de validation essaierait toujours de les valider.

    Cependant, si vous supprimez les données “unobtrusiveValidation” du formulaire en plus de “validationData”, cela a fonctionné comme un charme pour l’ajout et la suppression dynamics d’éléments que vous souhaitez valider ou non.

     $("form").removeData("validator"); $("form").removeData("unobtrusiveValidation"); $.validator.unobtrusive.parse("form"); 

    En fait, j’aime vraiment la simplicité de la solution @viggity et @Robins, alors je l’ai transformée en un petit plugin rapide:

     (function ($) { $.fn.updateValidation = function () { var $this = $(this); var form = $this.closest("form") .removeData("validator") .removeData("unobtrusiveValidation"); $.validator.unobtrusive.parse(form); return $this; }; })(jQuery); 

    Exemple d’utilisation:

     $("#DischargeOutcomeNumberOfVisits") .attr("data-val-range-min", this.checked ? "1" : "2") .updateValidation(); 

    J’ai le même problème. J’ai découvert qu’il n’est pas possible d’appeler $ .validator.unobtrusive.parse () sur le même formulaire deux fois. Lors du chargement initial du formulaire à partir du serveur, le formulaire est analysé automatiquement par la bibliothèque discrète. Lorsque vous ajoutez dynamicment un élément d’entrée au formulaire et que vous appelez à nouveau $ .validator.unobtrusive.parse (), cela ne fonctionnera pas. La même chose vaut pour parseElement ().

    La librairie discrète appelle la méthode validate du plugin jquery validate pour définir toutes les règles et tous les messages. Le problème est que, lorsqu’il est appelé à nouveau, le plug-in ne met pas à jour le nouvel ensemble de règles qui lui est donné.

    J’ai trouvé une solution brute: Avant d’appeler la méthode d’parsing sur la librairie non obstructive, je jette le validateur de formulaire:

     $('yourForm').removeData("validator"); 

    Désormais, lorsque la librairie discrète appelle la méthode validate, toutes les règles et tous les messages sont recréés, y compris les entrées ajoutées dynamicment.

    J’espère que cela t’aides

    J’utilise MVC 4 et JQuery 1.8, il semble que le morceau de code suivant soit nécessaire pour permettre à Jquery de valider dynamicment le contenu injecté via Ajax ou Jquery dans le DOM.

    J’ai créé une fonction modulaire qui accepte l’object Jquery du nouvel élément ajouté. Si vous avez cloné une nouvelle table avec l’id tblContacts utilisant Jquery en cliquant sur un bouton, puis incluez la fonction ci-dessous dans votre fichier js

     function fnValidateDynamicContent(element) { var currForm = element.closest("form"); currForm.removeData("validator"); currForm.removeData("unobtrusiveValidation"); $.validator.unobtrusive.parse(currForm); currForm.validate(); // This line is important and added for client side validation to sortinggger, without this it didn't fire client side errors. } 

    et appelez comme ceci:

     fnValidateDynamicContent("#tblContacts") 

    En prenant la solution de Xhalent marquée comme réponse ci-dessus, je l’ai un peu développée.

     $.validator.unobtrusive.parseDynamicContent = function (selector) { var $selector = $(selector), $jqValUnob = $.validator.unobtrusive, selectorsDataValAttr = $selector.attr('data-val'), $validationInputs = $selector.find(':input[data-val=true]'); if ((selectorsDataValAttr !== 'true') && ($validationInputs.length === 0)) { return; } if (selectorsDataValAttr === 'true') { $jqValUnob.parseElement(selector, true); } $validationInputs.each(function () { $jqValUnob.parseElement(this, true); }); //get the relevant form var $form = $selector.first().closest('form'); $jqValUnob.syncValdators($form); }; /* synchronizes the unobtrusive validation with jquery validator */ $.validator.unobtrusive.syncValdators = function ($form) { if ($.hasData($form[0])) { var unobtrusiveValidation = $form.data('unobtrusiveValidation'), validator = $form.validate(); // add validation rules from unobtrusive to jquery $.each(unobtrusiveValidation.options.rules, function (elname, elrules) { if (validator.settings.rules[elname] == undefined) { var args = {}; $.extend(args, elrules); args.messages = unobtrusiveValidation.options.messages[elname]; $("[name='" + elname + "']").rules("add", args); } else { $.each(elrules, function (rulename, data) { if (validator.settings.rules[elname][rulename] == undefined) { var args = {}; args[rulename] = data; args.messages = unobtrusiveValidation.options.messages[elname][rulename]; $("[name='" + elname + "']").rules("add", args); } }); } }); // remove all validation rules from jquery that arn't in unobtrusive $.each(validator.settings.rules, function (elname, elrules) { if (unobtrusiveValidation.options.rules[elname] === undefined) { delete validator.settings.rules[elname]; } else { $.each(elrules, function (rulename, data) { if (rulename !== "messages" && unobtrusiveValidation.options.rules[elname][rulename] === undefined) { delete validator.settings.rules[elname][rulename]; } }); } }); } }; $.validator.unobtrusive.unparseContent = function (selector) { var $selector = $(selector); // if its a text node, then exit if ($selector && $selector.length > 0 && $selector[0].nodeType === 3) { return; } var $form = $selector.first().closest('form'), unobtrusiveValidation = $form.data('unobtrusiveValidation'); $selector.find(":input[data-val=true]").each(function () { removeValidation($(this), unobtrusiveValidation); }); if ($selector.attr('data-val') === 'true') { removeValidation($selector, unobtrusiveValidation); } $.validator.unobtrusive.syncValdators($form); }; function removeValidation($element, unobtrusiveValidation) { var elname = $element.attr('name'); if (elname !== undefined) { $element.rules('remove'); if (unobtrusiveValidation) { if (unobtrusiveValidation.options.rules[elname]) { delete unobtrusiveValidation.options.rules[elname]; } if (unobtrusiveValidation.options.messages[elname]) { delete unobtrusiveValidation.options.messages[elname]; } } } } 

    Donc, en gros, cela fonctionne toujours comme la solution de Xhalent ci-dessus, mais j’ai ajouté la possibilité de supprimer les règles pour les éléments que vous retirez du dom. Ainsi, lorsque vous supprimez des éléments du Dom et que vous souhaitez les supprimer également, appelez:

     $.validator.unobtrusive.unparseContent('input.something'); 

    Pourquoi ne pas utiliser la fonction de règles directement à partir du document de validation jquery. Comme ça:

     $('#newField0').rules('add', { required: true, minlength: 2 }); //use Html.ValidationMessage will renders a span element, unobtrusive need it to display errors $('@Html.ValidationMessage("newField0")').insertAfter('#newField0'); 

    J’ai trouvé le script de code de @ Xhalent dans mon code et j’allais le supprimer car je ne l’utilisais pas, ce qui m’a amené à cette question SO.

    Ce code est assez propre et simple:

     jQuery.fn.unobtrusiveValidationForceBind = function () { //If you try to parse a form that is already parsed it won't update var $form = this .removeData("validator") /* added by the raw jquery.validate plugin */ .removeData("unobtrusiveValidation"); /* added by the jquery unobtrusive plugin */ $form.bindUnobtrusiveValidation(); } 

    Ensuite, pour appeler cette extension jQuery, utilisez simplement un sélecteur pour saisir votre formulaire:

     $('#formStart').unobtrusiveValidationForceBind(); 

    Alto!

    En cas de contenu dynamic, vous devez mettre à jour les validations discrètes comme ci-dessous et vérifier si le Form est valide lors de la soumission.

     function UpdateUnobtrusiveValidations(idForm) { $(idForm).removeData("validator").removeData("unobtrusiveValidation"); $.validator.unobtrusive.parse($(idForm)); }; $('#idDivPage').on('click', '#idSave', function (e) { e.preventDefault(); if (!$('#idForm').valid()) { // Form is invalid … so return return false; } else { // post data to server using ajax call // update Unobtrusive Validations again UpdateUnobtrusiveValidations('#idForm'); } }); 

    Cela fait un bout de temps que j’essaye de trouver des solutions et de réessayer plus tard (quand j’ai du temps libre, croyez-le ou non).

    Je ne sais pas si ce comportement aurait changé dans les nouvelles versions de jquery (nous utilisons 1.7.2) depuis la création ou le commentaire de ce thread, mais j’ai trouvé que .parseElement(inputElement) fonctionne .parseElement(inputElement) lorsque j’essaie d’append dynamicment éléments créés à un formulaire qui a déjà un validateur chargé. Cela a déjà été suggéré par @jamesfm (15 février 2011) dans l’un des commentaires ci-dessus, mais je l’ai négligé les premières fois où je travaillais là-dessus. Donc je l’ajoute comme une réponse séparée pour le rendre plus évident et parce que je pense que c’est une bonne solution et ne nécessite pas trop de frais généraux. Cela pourrait ne pas être pertinent pour toutes les questions soulevées dans les réponses ultérieures, mais je pense que ce serait une solution à la question initiale. Voici comment j’ai fait travailler les miennes:

     //row & textarea created dynamically by an async ajax call further up in the code var row = ...; //row reference from somewhere var textarea = row.find("textarea"); textarea.val("[someValue]"); //add max length rule to the text area textarea.rules('add', { maxlength: 2000 }); //parse the element to enable the validation on the dynamically added element $.validator.unobtrusive.parseElement(textarea); 

    Tout d’abord, je pense que l’appel devrait être à .validator, pas valider alors vous devez passer l’id du formulaire

     $.validator.unobtrusive.parse("#id"); 

    J’ai essayé la réponse vigoureuse et au début tout semblait fonctionner. Mais au bout d’un moment, j’ai remarqué que la validation ralentit péniblement, plus les éléments ajoutés dynamicment. La raison en est que sa solution ne dissocie pas les gestionnaires d’événements, mais en ajoute de nouveaux à chaque fois. Donc, si vous ajoutez 5 éléments, la validation est exécutée 6 fois au lieu d’une seule fois. Pour résoudre ce problème, vous devez dissocier les événements en plus des appels removeData.

     $("form").removeData("validator") .removeData("unobtrusiveValidation") .off("submit.validate click.validate focusin.validate focusout.validate keyup.validate invalid-form.validate"); $.validator.unobtrusive.parse("form");