web-dev-qa-db-fra.com

La validation non intrusive de MVC sur la case à cocher ne fonctionne pas

J'essaye d'implémenter le code comme mentionné dans ce post . En d'autres termes, j'essaie d'implémenter une validation discrète sur une case à cocher des termes et conditions. Si l'utilisateur n'a pas coché la case, l'entrée doit être marquée comme non valide. 

C'est le code du validateur côté serveur, j'ai ajouté:

/// <summary>
/// Validation attribute that demands that a boolean value must be true.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class MustBeTrueAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        return value != null && value is bool && (bool)value;
    }
}

C'est le modèle

[MustBeTrue(ErrorMessage = "You must accept the terms and conditions")]
[DisplayName("Accept terms and conditions")]
public bool AcceptsTerms { get; set; }

C'est mon avis:

@Html.EditorFor(x => x.AcceptTermsAndConditions)
@Html.LabelFor(x => x.AcceptTermsAndConditions)
@Html.ValidationMessageFor(x => x.AcceptTermsAndConditions)

et voici le jQuery que j'ai utilisé pour attacher le côté client du validateur:

$.validator.unobtrusive.adapters.addBool("mustbetrue", "required");

Le script côté client ne semble toutefois pas être actif. Chaque fois que j'appuie sur le bouton d'envoi, la validation des autres champs démarre, mais la validation des conditions générales ne semble pas s'activer. C'est à quoi ressemble le code dans Firebug après avoir cliqué sur le bouton d'envoi.

<input type="checkbox" value="true" name="AcceptTermsAndConditions" id="AcceptTermsAndConditions" data-val-required="The I confirm that I am authorised to join this website and I accept the terms and conditions field is required." data-val="true" class="check-box">
<input type="hidden" value="false" name="AcceptTermsAndConditions">
<label for="AcceptTermsAndConditions">I confirm that I am authorised to join this website and I accept the terms and conditions</label>
<span data-valmsg-replace="true" data-valmsg-for="AcceptTermsAndConditions" class="field-validation-valid"></span>

Des idées? Ai-je raté une étape? Ceci me conduit le pot!

Merci d'avance S

22
Sniffer

Renifleur,

En plus d'implémenter la solution de Darin, vous devez également modifier le fichier jquery.validate.unobtrusive.js. Dans ce fichier, vous devez ajouter une méthode de validation "mustbetrue", comme suit:

$jQval.addMethod("mustbetrue", function (value, element, param) {
    // check if dependency is met
    if (!this.depend(param, element))
        return "dependency-mismatch";
    return element.checked;
});

Ensuite (j'ai oublié d'ajouter ceci au début), vous devez également ajouter ce qui suit à jquery.validate.unobtrusive.js:

adapters.add("mustbetrue", function (options) {
    setValidationValues(options, "mustbetrue", true);
});

counsellorben

25
counsellorben

Vous devez implémenter IClientValidatable sur votre attribut personnalisé afin de lier le nom d'adaptateur mustbetrue que vous enregistrez côté client avec cet attribut:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class MustBeTrueAttribute : ValidationAttribute, IClientValidatable
{
    public override bool IsValid(object value)
    {
        return value != null && value is bool && (bool)value;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        yield return new ModelClientValidationRule
        {
            ErrorMessage = this.ErrorMessage,
            ValidationType = "mustbetrue"
        };
    }
}

METTRE À JOUR:

Exemple de travail complet.

Modèle:

public class MyViewModel
{
    [MustBeTrue(ErrorMessage = "You must accept the terms and conditions")]
    [DisplayName("Accept terms and conditions")]
    public bool AcceptsTerms { get; set; }
}

Manette:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new MyViewModel();
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}

Vue:

@model MyViewModel

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
<script type="text/javascript">
    $.validator.unobtrusive.adapters.addBool("mustbetrue", "required");
</script>

@using (Html.BeginForm())
{
    @Html.CheckBoxFor(x => x.AcceptsTerms)
    @Html.LabelFor(x => x.AcceptsTerms)
    @Html.ValidationMessageFor(x => x.AcceptsTerms)
    <input type="submit" value="OK" />
}
36
Darin Dimitrov

Je ne sais pas pourquoi cela n'a pas fonctionné pour moi, mais j'ai choisi d'utiliser votre code et de faire quelque chose de légèrement différent. 

Sur mon chargement JavaScript, j’ajoute ce qui suit: la case à cocher est activée, ce qui déclenche la validation sans entrave si vous cochez la case et décochez-la. Aussi, si vous soumettez le formulaire. 

$(function () {
        $(".checkboxonblurenabled").change(function () {
            $('form').validate().element(this);
        });
});

Vous devez également ajouter la classe CSS à votre case à cocher, comme ceci.

@Html.CheckBoxFor(model => model.AgreeToPrivacyPolicy, new { @class = "checkboxonblurenabled"})

Donc, nous devons maintenant connecter le modèle et mettre en classe afin de gérer la validation côté serveur (que je réutilise d’en haut) mais en modifiant légèrement la discrétion.

Voici l'attribut client qui étend IClientValidate comme dans l'exemple ci-dessus ...

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class MustBeTrueAttribute : ValidationAttribute, IClientValidatable
{
    public override bool IsValid(object value)
    {
        return value != null && value is bool && (bool)value;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        yield return new ModelClientValidationRule
        {
            ErrorMessage = this.ErrorMessage,
            ValidationType = "mustbetrue"
        };
    }
}

Dans votre modèle, la propriété object définit les notations d'attribut souhaitées.

 [MustBeTrue(ErrorMessage = "Confirm you have read and agree to our privacy policy")]
    [Display(Name = "Privacy policy")]
    public bool AgreeToPrivacyPolicy { get; set; }

Ok, nous sommes prêts à mettre en JavaScript.

(function ($) {
    /*
    START CHECK MUST BE TRUE - UNOBTRUSIVE JAVASCRIPT
    START CHECK MUST BE TRUE - UNOBTRUSIVE JAVASCRIPT
    START CHECK MUST BE TRUE - UNOBTRUSIVE JAVASCRIPT
    */
    jQuery.validator.unobtrusive.adapters.add("mustbetrue", ['maxint'], function (options) {
        options.rules["mustbetrue"] = options.params;
        options.messages["mustbetrue"] = options.message;
    });

    jQuery.validator.addMethod("mustbetrue", function (value, element, params) {

        if ($(element).is(':checked')) {
            return true;
        }
        else {
            return false;
        }
    });
    /*
    START CHECK MAX INT - UNOBTRUSIVE JAVASCRIPT
    START CHECK MAX INT - UNOBTRUSIVE JAVASCRIPT
    START CHECK MAX INT - UNOBTRUSIVE JAVASCRIPT
    */



} (jQuery));

Ce qui fait que ça marche, c'est ... bien. Après avoir examiné le balisage HTML après avoir tenté de donner la réponse suggérée ci-dessus, toutes mes valeurs étaient définies sur true, mais ma case à cocher était fausse. J'ai donc décidé de laisser jQuery résoudre ce problème en utilisant IsChecked.

5
Adam

Pour ceux qu'aucune de ces solutions ne fonctionne:

Je travaille avec Razor MVC 4 en utilisant .Net Framework 4 et la dernière version de jquery pour valider les fichiers de script.

Après avoir implémenté la validation d'attribut personnalisé côté client et côté serveur, cela ne fonctionne toujours pas. Mon formulaire est posté de toute façon.

Voici donc le piège: Le script de validation JQuery a pour paramètre par défaut ignorer les balises masquées, où hidden est http://api.jquery.com/hidden-selector/ , ce ne sera pas un problème normalement, mais le style @ Html.CheckBoxFor que j’utilise est personnalisé avec un style CSS3 qui modifie l’affichage en aucun et une image personnalisée de la case à cocher est affichée, de sorte qu’il n’exécutera jamais la règle de validation cochée.

Ma solution de contournement consistait à ajouter cette ligne avant la déclaration de la règle de validation client personnalisée:

$.validator.defaults.ignore = "";

son rôle est de remplacer le paramètre ignorer pour toutes les validations de la page en cours, en remarquant qu’il pouvait maintenant exécuter des validations sur un champ masqué également (un effet secondaire).

2
Jesus Mogollon
<script>
    $(function () {
        $('#btnconfirm').click(function () {
            if ($("#chk").attr('checked') !== undefined ){
                return true;
            }
            else {

                alert("Please Select Checkbox ");
                return false;
            }
        });

    });
</script>
<div style="float: left">
                    <input type="checkbox" name="chk" id="chk"  />
                    I read and accept the terms and Conditions of registration
                </div>
  <input type="submit" value="Confirm"  id="btnconfirm" />
1
kavitha Reddy
/// <summary> 
///  Summary : -CheckBox for or input type check required validation is not working the root cause and solution as follows
///
///  Problem :
///  The key to this problem lies in interpretation of jQuery validation 'required' rule. I digged a little and find a specific code inside a jquery.validate.unobtrusive.js file:
///  adapters.add("required", function (options) {
///  if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") {
///    setValidationValues(options, "required", true);
///    }
///   });
///   
///  Fix: (Jquery script fix at page level added in to check box required area)
///  jQuery.validator.unobtrusive.adapters.add("brequired", function (options) {
///   if (options.element.tagName.toUpperCase() == "INPUT" && options.element.type.toUpperCase() == "CHECKBOX") {
///              options.rules["required"] = true;
///   if (options.message) {
///                   options.messages["required"] = options.message;
///                       }
///  Fix : (C# Code for MVC validation)
///  You can see it inherits from common RequiredAttribute. Moreover it implements IClientValidateable. This is to make assure that rule will be propagated to client side (jQuery validation) as well.
///  
///  Annotation example :
///   [BooleanRequired]
///   public bool iAgree { get; set' }
///    

/// </summary>


public class BooleanRequired : RequiredAttribute, IClientValidatable
{

    public BooleanRequired()
    {
    }

    public override bool IsValid(object value)
    {
        return value != null && (bool)value == true;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        return new ModelClientValidationRule[] { new ModelClientValidationRule() { ValidationType = "brequired", ErrorMessage = this.ErrorMessage } };
    }
}
0