web-dev-qa-db-fra.com

Comment ajouter une fonction «submitHandler» lors de l'utilisation de jQuery Unobtrusive Validation?

Je valide un formulaire à l'aide des nouvelles fonctionnalités de validation discrètes dans ASP.NET MVC 3.

Il n'y a donc pas de code que j'ai écrit pour configurer jQuery validate pour commencer à valider mon formulaire. Tout est fait en chargeant la bibliothèque jQuery.validate.unobtrusive.js.

Malheureusement, je dois frapper un "êtes-vous sûr?" boîte de message lorsque le formulaire est valide mais avant de le soumettre. Avec jQuery validate, vous ajouteriez l'option handleSubmit lors de l'initialisation comme ceci:

$("#my_form").validate({
  rules: {
    field1: "required",
    field1: {email: true },
    field2: "required"
  },
  submitHandler: function(form) {
     if(confirm('Are you sure?')) {
       form.submit();
     }
  }
});

Mais vous n'avez pas besoin d'initialiser lorsque vous utilisez la bibliothèque discrète.

Des idées où/comment puis-je ajouter un gestionnaire de soumission dans ce cas?

THX

44
WooWaaBob

La bibliothèque discrète attachera le validateur sur tous les formulaires, vous devez donc remplacer le submitHandler de cette façon:

$("form").data("validator").settings.submitHandler = function (form) { alert('submit'); form.submit(); };
69
petrhaus

J'ai trouvé cette question en cherchant un moyen de définir le invalidHandler, par opposition au submitHandler. Fait intéressant, vous ne pouvez pas définir invalidHandler de la même manière lorsque vous utilisez une validation discrète.

La fonction n'est pas déclenchée lorsqu'un formulaire non valide est détecté:

$("form").data("validator").settings.invalidHandler = function (form, validator) {
    alert('invalid!');
};

Cette approche fonctionne:

$("form").bind("invalid-form.validate", function () {
  alert('invalid!');
});

Cela semble être dû à la façon dont le script jquery.validate.unobtrusive.js initialise le plug-in Validate et à la façon dont le plug-in appelle le gestionnaire.

63
DGreen

Les résultats suivants peuvent être intéressants pour comprendre la différence entre:

submitHandler: Appelé lorsque le formulaire est validé avec succès - juste avant la publication du serveur
invalidHandler: Appelé si la validation échoue et qu'il n'y a pas de retour

La solution de @ DGreen semble définitivement être le meilleur moyen d'injecter une gestion spéciale si la validation du formulaire échoue et que vous devez faire quelque chose comme afficher un résumé de validation pop-up (invalidHandler)

$("form").bind("invalid-form.validate", function () {
  alert('invalid!');
});

La solution @PeteHaus est la meilleure façon de faire quelque chose si vous voulez empêcher la publication d'un formulaire validé avec succès (submitHandler)

$("form").data("validator").settings.submitHandler = function (form) { 
                                                     alert('submit'); form.submit(); };

Cependant, j'étais légèrement préoccupé par le comportement que je remplaçais (ou ne remplaçais pas) en me liant à la méthode .validate Comme ceci - et pourquoi je devais faire différemment. J'ai donc vérifié la source. Je recommande fortement à quiconque souhaite mieux comprendre cette procédure de le faire également - insérez des instructions 'alert' ou des instructions 'debugger' et c'est assez facile à suivre *

Quoi qu'il en soit, il s'avère que lorsque le gestionnaire jquery.validate.unobtrusive Initialise le plugin jquery.validate, Il le fait dans la méthode parseElement() en récupérant les options créées par la méthode validationInfo().

ValidationInfo() renvoie les options comme ceci:

 options: {  // options structure passed to jQuery Validate's validate() method
             errorClass: "input-validation-error",
             errorElement: "span",
             errorPlacement: $.proxy(onError, form),
             invalidHandler: $.proxy(onErrors, form),
             messages: {},
             rules: {},
             success: $.proxy(onSuccess, form)
           },

La méthode onErrors() dans jquery.validate.unobtrusive Est responsable de la création dynamique du panneau récapitulatif de validation pour MVC. Si vous ne créez pas de panneau de résumé de validation (avec @Html.ValidationSummary() qui doit être contenue dans le corps du FORM), cette méthode est complètement inerte et ne fait rien, vous n'avez donc pas à vous inquiéter.

function onErrors(event, validator) {  // 'this' is the form elementz
    var container = $(this).find("[data-valmsg-summary=true]"),
        list = container.find("ul");

    if (list && list.length && validator.errorList.length) {
        list.empty();
        container.addClass("validation-summary-errors").removeClass("validation-summary-valid");

        $.each(validator.errorList, function () {
            $("<li />").html(this.message).appendTo(list);
        });
    }
}

Si vous le voulez vraiment, vous pouvez dissocier le gestionnaire jquery.validate.unobtrusive Comme ceci - mais je ne me dérangerais pas

 $("form").unbind("invalid-form.validate"); // unbind default MS handler

Si vous vous demandez pourquoi cela fonctionne

 $("form").data("validator").settings.submitHandler = ...

et cela ne fonctionne pas

 $("form").data("validator").settings.invalidHandler = ...

c'est parce que submitHandler est explicitement appelé à l'intérieur de jquery.validate lors de la validation. Par conséquent, peu importe à quel point il est défini.

 validator.settings.submitHandler.call( validator, validator.currentForm );

mais le invalidHandler est lié à un événement pendant init() comme ceci donc si vous le définissez dans votre propre code, il est trop tard

if (this.settings.invalidHandler)
    $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);

Un petit pas dans le code fait parfois beaucoup comprendre! J'espère que cela t'aides

* Assurez-vous que la minification dans les bundles n'est pas activée.

34
Simon_Weaver

Je préfère injecter un gestionnaire d'événements, afin qu'il puisse être lié à ... :)

//somewhere in your global scripts
$("form").data("validator").settings.submitHandler = function (form) {
    var ret = $(form).trigger('before-submit');
    if (ret !== false) form.submit();
};

De cette façon, je peux me lier là où c'est nécessaire ...

//in your view script(s)
$("form").bind("before-submit", function() {
    return confirm("Are you sure?");
});
11
Tracker1

J'ai basé cela sur la réponse originale, qui n'a pas fonctionné pour moi. Je suppose que les choses ont changé dans jQuery.

Comme d'habitude, prenez ce code et ajoutez une vérification d'erreur abondante: D J'utilise un code similaire pour empêcher les doubles soumissions sur nos formulaires, et cela fonctionne très bien dans IE8 + (à partir de mvc4 et jquery 1.8.x).

$("#myFormId").confirmAfterValidation();

// placed outside of a $(function(){ scope
jQuery.fn.confirmAfterValidation = function () {
    // do error checking first.  should be null if no handler already
    $(this).data('validator').settings.submitHandler = confirmValidForm;
};

function confirmValidForm(form) {
    var validator = $(this);
    var f = $(form);
    if (confirm("really really submit?")) {
        // unbind so our handler doesn't get called again, and submit
        f.unbind('submit').submit();
    }
        // return value is _ignored_ by jquery.validate, so we have to set
        // the flag on the validator itself, but it should cancel the submit
        // anyway if we have a submitHandler
        validator.cancelSubmit = true;
    }
}
1
Andrew Backer