web-dev-qa-db-fra.com

MVC3: case à cocher obligatoire via jQuery validate?

Je souhaite que ma case "Accepter les conditions" soit obligatoire à l'aide de jQuery validate, dans un projet MVC3. Je reçois actuellement la validation serveur/client DRY/SPOT de "attributs d'annotation de données MS" + "validation jQuery MS MVC3 non intrusive".

Voici un test autonome (HTML brut généré par MVC3). Pourquoi ça ne marche pas, s'il te plait? Lorsqu'elle est exécutée, la validation garantit que le champ "Nom du contact" est rempli, mais ne se soucie pas de l'état de la case à cocher.

<!DOCTYPE html>

<html>
<head>
    <title>RequiredCheckbox</title>

    <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
    <script type="text/javascript" src="//ajax.Microsoft.com/ajax/jQuery.Validate/1.7/jQuery.Validate.js"></script>
    <script type="text/javascript" src="//ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.js"></script>
    <script type="text/javascript" language="javascript">
        $(function () {
            // http://itmeze.com/2010/12/checkbox-has-to-be-checked-with-unobtrusive-jquery-validation-and-asp-net-mvc-3/
            $.validator.unobtrusive.adapters.add("mandatory", function (options) {
                    options.rules["required"] = true;
                    if (options.message) {
                        options.messages["required"] = options.message;
                    }
                }
            });
            $.validator.unobtrusive.parse(document);
        });
    </script>

</head>

<body>
    <div>
        <form>
            <input data-val="true" data-val-mandatory="The field Terms Are Accepted is invalid." id="isTermsAccepted" name="isTermsAccepted" type="checkbox" value="true" />
            <input name="isTermsAccepted" type="hidden" value="false" />
            <span class="field-validation-valid" data-valmsg-for="isTermsAccepted" data-valmsg-replace="true"></span>

            <input data-val="true" data-val-required="The Contact Name field is required." id="contactName" name="contactName" type="text" value="" />
            <span class="field-validation-valid" data-valmsg-for="contactName" data-valmsg-replace="true"></span>
            <button type="submit">Submit</button>
        </form>
    </div>
</body>
</html>





Le reste de ce post est juste mes notes de recherche.

La définition de l'attribut d'annotation de données [obligatoire] n'aide pas:
http://forums.89.biz/forums/MVC+3+Unobtrusive+validation+does+not+work+with+checkboxes+(jquery+validation)+and+the+fix+for+ il .

C'est très bien. Ce que "requis" signifie pour une case à cocher est évidemment une guerre sainte dans laquelle je ne veux pas me lancer, où MS pensait en savoir plus que l'équipe JQuery. La contraindre localement devrait être une simple question de:
$("form").validate({ rules: { cbAgreeToTerms: "required" } });

...droite? non, à cause de:
http://blog.waynebrantley.com/2011/01/mvc3-breaks-any-manual-use-of-jquery.html
http://pinoytech.org/question/4824071/microsofts-jquery-validate-unobtrusive-makes-other-val-validators-skip-validation

QUOI? C'est assez puant cheezy! (IMHO, bien sûr.)

Maintenant, j'ai essayé cette solution:
http://itmeze.com/2010/12/checkbox-has-to-be-checked-with-unobtrusive-jquery-validation-and-asp-net-mvc-3/
Et ça n'a pas marché pour moi. Les commentaires pendantes de cet auteur et l'utilisation un peu culte de la cargaison du test inversé CHECKBOX de son article précédent me font me demander si cela fonctionne réellement pour lui/elle, alors quel autre vaudou était impliqué?

Notez que je pense que le dernier extrait de JS est équivalent à l'agent de nettoyage:
$.validator.unobtrusive.adapters.addBool("brequired", "required"); Cela a été suggéré par le dernier message de:
http://forums.asp.net/p/1648319/4281140.aspx#4281140
Mais remarquez que l'auteur commente qu'il ne l'avait pas encore débogué. Cela n'a pas fonctionné pour moi, et en lisant entre les lignes, je pense qu'il veut dire que cela n'a pas fonctionné pour lui?

Les appels unobtrusive.js s’analysant sur docready, j’ai donc essayé de l’appeler, mais cela ne m’a pas aidé.
$.validator.unobtrusive.parse(document); J'ai également trouvé quelques articles similaires et aucun ne parle d'exiger l'initialisation. Peut-être qu’ils modifient tous localement le fichier original/public unobtrusive.js? Je préférerais ne pas l'aider, n'est-ce pas pour cela que les adaptateurs sont?

J'ai trouvé des articles de pile-débordement, sensiblement les mêmes, ainsi que des exemples plus complexes:
ASP .Net MVC 3 validation client personnalisée discrète
Effectuer une validation côté client pour l'attribut personnalisé
http://xhalent.wordpress.com/2011/01/27/custom-unobstrusive-jquery-validation-in-asp-net-mvc-3/
Mais je ne vois rien de différent de ce que j'ai déjà essayé.

Est-ce que cela fonctionne vraiment pour les gens? Pourquoi je ne peux pas le faire fonctionner pour moi?

44
shannon

Il suffit de changer votre javascript pour ceci:

(function ($) {
    // http://itmeze.com/2010/12/checkbox-has-to-be-checked-with-unobtrusive-jquery-validation-and-asp-net-mvc-3/
    $.validator.unobtrusive.adapters.add("mandatory", function (options) {
        options.rules["required"] = true;
        if (options.message) {
            options.messages["required"] = options.message;
        }                
    });            
} (jQuery));

Cependant, vous n'avez pas besoin d'écrire votre propre adaptateur et vous pouvez simplement utiliser:

(function ($) {
    $.validator.unobtrusive.adapters.addBool("mandatory", "required");
} (jQuery));
32
Paul Hiles

J'ai résumé ici le code source qui fonctionne correctement et qui résulte de l'application de la réponse acceptée. J'espère que vous le trouverez utile.

RequiredCheckbox.aspx

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<RegistrationViewModel>" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title>RequiredCheckbox</title>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" type="text/javascript"></script>
    <script src="//ajax.Microsoft.com/ajax/jQuery.Validate/1.7/jQuery.Validate.js" type="text/javascript"></script>
    <script src="//ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.js" type="text/javascript"></script>
    <script type="text/javascript" language="javascript">
        $.validator.unobtrusive.adapters.addBool("mandatory", "required");
    </script>
</head>
<body>
    <div>
        <% 
        // These directives can occur in web.config instead
        Html.EnableUnobtrusiveJavaScript();
        Html.EnableClientValidation();
        using (Html.BeginForm())
        { %>
            <%: Html.CheckBoxFor(model => model.IsTermsAccepted)%>
            <%: Html.ValidationMessageFor(model => model.IsTermsAccepted)%>

            <%: Html.TextBoxFor(model => model.ContactName)%>
            <%: Html.ValidationMessageFor(model => model.ContactName)%>
            <button type="submit">Submit</button>
        <% } %>
    </div>
</body>
</html>

RegistrationViewModel.cs

using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

public class RegistrationViewModel {
    [Mandatory (ErrorMessage="You must agree to the Terms to register.")]
    [DisplayName("Terms Accepted")]
    public bool isTermsAccepted { get; set; }

    [Required]
    [DisplayName("Contact Name")]
    public string contactName { get; set; }
}

MandatoryAttribute.cs

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

public class MandatoryAttribute : ValidationAttribute, IClientValidatable
{
    public override bool IsValid(object value)
    {
        return (!(value is bool) || (bool)value);
    }
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        ModelClientValidationRule rule = new ModelClientValidationRule();
        rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
        rule.ValidationType = "mandatory";
        yield return rule;
    }
}
60
shannon
<asp:Content ID="Content1" ContentPlaceHolderID="MainContentPlaceHolder" runat="server">
    <h2>
        Save New Contact</h2>
    <%using (Html.BeginForm("SaveContact", "Contact", FormMethod.Post, new { id = "UserImportTypeForm", @autocomplete = "off" })) %>
    <%{ %>
    <table style="height: 100px;">
        <tr>
            <td>
                Import Type :
            </td>

        </tr>
        <tr>
            <td>
                Is Verified
            </td>
            <td>
                <%-- <%=Html.TextBox("UserContactModel.IsVerified", new SelectList(Model.IsVerified, "IsVerified"), new { })%>>--%>
                <%-- <input type="text" name="txtIsVerified" id="txtIsVerified" />--%>
                <%-- <%= Html.TextBox("txtIsVerified")%>--%>
                <%=Html.CheckBox("SelectedUserContact.IsVerified", Convert.ToBoolean(Model.SelectedUserContact.IsVerified) )%>
                <%=Html.ValidationSummary("txtIsVerified", "*")%>
            </td>
        </tr>
        <tr>
            <td>
                First Name
            </td>
            <td>
                <%--<input type="text" name="txtFirstName" id="txtFirstName" />--%>
                <%=Html.TextBox ("SelectedUserContact.FirstName", Model.SelectedUserContact.FirstName )%>
                <%-- <%=Html.ValidationSummary("FirstName", "*")%>--%>
            </td>
        </tr>
        <tr>
            <td>
                Last Name
            </td>
            <td>
                <%--<input type="text" name="txtLastName" id="txtLastName" />--%>
                <%=Html.TextBox("SelectedUserContact.LastName", Model.SelectedUserContact.LastName)%>
                <%=Html.ValidationSummary("LastName", "*")%>
            </td>
        </tr>
        <tr>
            <td>
                Contact ID
            </td>
            <td>
                <%=Html.TextBox("SelectedUserContact.ContactID",Model.SelectedUserContact.ContactID) %>
                <%=Html.ValidationSummary("ContactID","*") %>
            </td>
        </tr>
        <tr>
            <td align="right">
                <input type="submit" value="Save" name="btnSave" id="btnSave" />
            </td>
            <td>
                <input type="button" value="Cancel" name="btnCancel" id="btnCancel" />
            </td>
        </tr>
    </table>
    <%} %>
    <script src="../../Scripts/jquery.validate.js" type="text/javascript"></script>
    <script language="javascript" type="text/javascript">

        $("#UserImportTypeForm").validate({
            rules:
    {

        "SelectedUserContact.FirstName": { required: true },
        "SelectedUserContact.LastName": { required: true },
        "SelectedUserContact.ContactID": {required:true}
    },
            messages:
    {

        "SelectedUserContact.FirstName": { required: "*" },
        "SelectedUserContact.LastName": { required: "*" },
        "SelectedUserContact.ContactID": { required: "*" },

    }
        });



    </script>
</asp:Content>
0
vikram