61 votes

Appeler manuellement la validation côté client de MVC 3 pour les messages ajax

Je suis en train de créer une application web MVC 3. Je veux utiliser les annotations de données sur ma classe d'entité et ensuite utiliser une validation discrète côté client avant de renvoyer un message au serveur. Cela fonctionne bien lors d'un envoi normal. J'obtiens la validation et le résumé de la validation si l'un des champs n'est pas valide. Cependant, je veux renvoyer les informations par ajax et json. Comment puis-je valider "manuellement" le formulaire du côté client, puis renvoyer l'information au serveur par ajax ? Vous trouverez ci-dessous une version résumée de mon code.

  public class Customer
    {
        [Required(ErrorMessage = "The customer's first name is required.")]
        public string FirstName { get; set; }

        [Required(ErrorMessage = "The customer's last name is required.")]
        public string LastName { get; set; }
    }

    <% using (Html.BeginForm()) { %>

    <%: Html.LabelFor(model => model.FirstName, "First Name")%>
    <%: Html.TextBoxFor(model => model.FirstName, new { @class = "TextBox", id = "Customer.FirstName" })%>
    <%: Html.ValidationMessageFor(model => model.FirstName, "*")%>

    <%: Html.LabelFor(model => model.LastName, "Last Name")%>
    <%: Html.TextBoxFor(model => model.LastName, new { @class = "TextBox", id = "Customer.LastName" })%>
    <%: Html.ValidationMessageFor(model => model.LastName, "*")%>

    <div id="CustomerEditSave" class="Button CustomerEditButtons" style="margin-right:40px;">
       <a href="#">Save</a>
    </div>

    <%: Html.ValidationSummary(true) %>

    <% } %>

J'ai essayé ce code mais il ne valide que le prénom et n'affiche pas le résumé de la validation.

    $("#CustomerEditSave").click(function () {
        $(form).validate();
        //Ajax call here
    });

97voto

Paul Points 7328

Essayez :

//using the form as the jQuery selector (recommended)
$('form').submit(function(evt) {
    evt.preventDefault();
    var $form = $(this);
    if($form.valid()) {
        //Ajax call here
    }
});

//using the click event on the submit button
$('#buttonId').click(function(evt) {
    evt.preventDefault();
    var $form = $('form');
    if($form.valid()) {
        //Ajax call here
    }
});

Cela devrait fonctionner avec les appels jQuery ajax et MSAjax. Vous pouvez également essayer d'utiliser http://nuget.org/packages/TakeCommand.js o https://github.com/webadvanced/takeCommand il s'en chargera automatiquement pour vous.

0 votes

Comme je l'ai mentionné dans le commentaire ci-dessous - effectuer des appels ajax dans le clic peut avoir pour résultat que l'appel submit l'emporte sur l'appel ajax si vous ne gérez pas explicitement l'annulation de l'action submit en retournant false... ce qui signifie que la solution nécessite l'écriture de deux fonctions au lieu d'une...

1 votes

@DrRob, vous ne devez jamais retourner false, vous devez capturer l'événement jQuery comme paramètre et appeler preventDefault(). Si votre gestionnaire de clic utilise return false pour empêcher la navigation du navigateur, cela ouvre la possibilité que l'interpréteur n'atteigne pas l'instruction de retour et que le navigateur procède à l'exécution du comportement par défaut de la balise d'ancrage. C'est ce qui a causé votre problème, et non le fait que vous utilisiez click vs submit. L'avantage d'utiliser event.preventDefault() est que vous pouvez l'ajouter en tant que première ligne du gestionnaire, garantissant ainsi que le comportement par défaut de l'ancre ne sera pas exécuté.

3 votes

Evt.preventDefault() ; j'adore cette méthode, que j'utilise tout le temps maintenant au lieu de renvoyer false.

24voto

Rob Points 4309

Cela fait des jours que je m'amuse avec la validation côté client de MVC :

N'utilisez pas .click mais .submit :

$("#MyForm").on('submit',function () {

    if($("#MyForm").valid())
    {
        //Do ajax stuff
    }

    //Return false regardless of validation to stop form submitting
    //prior to ajax doing its thing
    return false;
});

Je vais ajouter une mise à jour à ce sujet, envisagez d'annuler l'événement plutôt que de renvoyer false (ou faites les deux) :

$("#MyForm").on('submit',function (e) {

    if($("#MyForm").valid())
    {
        //Do ajax stuff
    }

    e.preventDefault();

    //Return false regardless of validation to stop form submitting
    //prior to ajax doing its thing
    return false;
});

0 votes

Excellente solution. Merci beaucoup. J'ai perdu du temps sur cette question ces deux derniers jours.

7 votes

Et une autre note, assurez-vous que jquery.validate.min.js et jquery.validate.unobtrusive.min.js sont référencés sur la page ou votre formulaire n'aura pas d'indicateur d'état. .valid() méthode.

0 votes

@juhan_h +1 - Totalement d'accord avec vous... J'oublie toujours cela ;-)

10voto

Chris Goodman Points 13

Au moins dans mon cas (MVC 5), il était également nécessaire d'ajouter le code suivant ou sinon .valid() retournerait toujours vrai :

$(function () {
$(document).ajaxComplete(function(event, request, settings){
    //re-parse the DOM after Ajax to enable client validation for any new form fields that have it enabled
    $.validator.unobtrusive.parse(document);
});

}) ;

Voir http://johnculviner.com/the-unobtrusive-libraries-client-validation-on-ajax-in-asp-net-mvc-3/

0 votes

Whoa !! J'ai cherché pendant si longtemps. Je suis enfin tombé sur ce site. Merci beaucoup !

4voto

awrigley Points 6468

IMPORTANT!! :

La solution de Paul est la réponse correcte à la question, pas celle du Dr Rob.

Bien que vous puissiez simplement utiliser valid() au lieu de validate().form().

Mais surtout, il n'y a aucune raison de restreindre votre code comme le suggère le Dr Rob, c'est-à-dire de ne pas utiliser .click et de n'utiliser que .submit. Ce n'est pas ce qui a résolu le problème ! Ce qui a résolu le problème était d'envelopper l'appel $.ajax(...) dans l'instruction if. C'est-à-dire :

if($("#MyForm").valid())
{
    //call to $.ajax or equivalent goes in here.
}

Je pense que cela doit être clarifié, car sinon, la véritable réponse au problème est obscurcie.

4 votes

Le problème de l'utilisation de Click est que vous devez toujours gérer l'événement Submit du formulaire. Si vous faites un appel ajax avec l'événement Click, il peut être supplanté par l'action Submit si vous ne le gérez pas explicitement... Ma solution est, j'en suis sûr, une parmi d'autres, je n'ai pas voté comme étant la réponse que d'autres personnes ont fait... Comme je l'ai dit dans mon post, j'ai passé pas mal de temps à essayer de faire faire à Click des choses qu'il ne voulait pas faire, dès que j'ai passé à Submit, cela a résolu "MON" problème.

0 votes

Désolé de ressusciter les morts avec ce message, mais je veux ajouter quelques informations pour les passants. Le problème le plus évident est qu'il n'est pas nécessaire de cliquer sur un bouton pour soumettre un formulaire, ce qui entraîne un comportement étrange entre navigateurs. Si un utilisateur appuie sur la touche "entrée" d'un champ de formulaire, le navigateur pourrait soit assez gentil pour chercher un bouton de soumission sur lequel déclencher un événement de clic. Sinon, il soumettra simplement le formulaire sans événement de clic, quel que soit le bouton d'envoi. Après tout, si pour une raison quelconque, vous avez plusieurs boutons d'envoi... comment savoir lequel doit être cliqué lors de l'envoi ?

0 votes

@Aejay Je suis d'accord. J'ai pratiquement cessé d'utiliser <input type="submit" /> dans tout code qui utilise des appels Ajax. Je gère l'appel Ajax de toute façon, pas besoin d'ajouter des problèmes avec les soumissions possibles. Il suffit d'utiliser <input type="button" /> et de gérer les actions que vous voulez.

1voto

Dipak Pandey Points 21

$(VotreForm).data('unobtrusiveValidation').validate()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X