Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery.validator.unobtrusive.adapters.addMinMax round trips, doesn't work in MVC3

I am creating a day range validator using DataAnnotations, jQuery.validate and jquery.validate.unobtrusive. I've already read the following: http://bradwilson.typepad.com/blog/2010/10/mvc3-unobtrusive-validation.html

http://weblogs.asp.net/mikaelsoderstrom/archive/2010/10/06/unobtrusive-validation-in-asp-net-mvc-3.aspx

and other but can't post them (noob)

As well as most of the post on SO. I'm baning my head against a wall, any help could be rewardde with beer/food/code/etc ;) Anyway here's the code:

I have a model object with the following parameter:

[Display(Name = "Start date"), 
 DayRange(0, 5, ErrorMessage = "The Start Date must be between today and 5 days time.")]
public DateTime StartDate { get; set; }

DayRange is a custom attribute class :

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class DayRangeAttribute : RangeAttribute, IClientValidatable
{
    private int _minimumDays;
    private int _maximumDays;

    public DayRangeAttribute(int minimumDays, int maximumDays) : base(minimumDays, maximumDays) 
    {
        _minimumDays = minimumDays;
        _maximumDays = maximumDays;
    }

    public override bool IsValid(object value)
    {
        var dateToBeTested = value as DateTime?;
        return dateToBeTested.HasValue && dateToBeTested.Value >= DateTime.Today.AddDays(_minimumDays) && dateToBeTested.Value <= DateTime.Today.AddDays(_maximumDays);
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
                         {
                             ErrorMessage = this.ErrorMessage,
                             ValidationType = "dayrange"
                         };
        rule.ValidationParameters.Add("min", _minimumDays);
        rule.ValidationParameters.Add("max", _maximumDays);
        yield return rule;
    }
}

I have the following in my web.config:

<appSettings>
    <add key="ClientValidationEnabled" value="true"/>
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
</appSettings>

I have have following JS trigger before the document is ready (have tried triggering it when the doc is ready too ):

jQuery.validator.addMethod('dayrange', function (value, element, param) {
    if (!value) return false;
    var now = Date();
    var dateValue = Date.parse(value);
    var minDate = now.setDate(now.getDate() - param.min);
    var maxDate = now.setDate(now.getDate() + param.max);

    return this.optional(element) && dateValue >= minDate && dateValue <= maxDate;
}, 'Must fall in range');

jQuery.validator.unobtrusive.adapters.addMinMax('dayrange', 'minlength', 'maxlength', 'dayrange');

What am I doing wrong? Thanks in advance, Jol

like image 488
jolySoft Avatar asked Jun 02 '11 15:06

jolySoft


People also ask

How does jquery unobtrusive validation work?

Unobtrusive Validation means without writing a lot of validation code, you can perform simple client-side validation by adding the suitable attributes and including the suitable script files. data-val-required=”This is required.”

What is validator unobtrusive parse?

validator. unobtrusive. parse(selector) method to force parsing. This method parses all the HTML elements in the specified selector and looks for input elements decorated with the [data-val=true] attribute value and enables validation according to the data-val-* attribute values.

How do I turn off unobtrusive validation?

You can disable the unobtrusive validation from within the razor code via this Html Helper property: HtmlHelper. ClientValidationEnabled = false; That way you can have unobtrusive validation on and off for different forms according to this setting in their particular view/partial view.


2 Answers

Solved! I forgot/didn't understand that you have to pass jQuery itself into the function closure. Therefore the custom validator on the client side should look like this:

$(function () {
    jQuery.validator.addMethod('dayRange', function (value, element, param) {
        if (!value) return false;
        var valueDateParts = value.split(param.seperator);
        var minDate = new Date();
        var maxDate = new Date();
        var now = new Date();
        var dateValue = new Date(valueDateParts[2],
                            (valueDateParts[1] - 1),
                             valueDateParts[0],
                             now.getHours(),
                             now.getMinutes(),
                             (now.getSeconds()+5));

        minDate.setDate(minDate.getDate() - parseInt(param.min));
        maxDate.setDate(maxDate.getDate() + parseInt(param.max));

    return dateValue >= minDate && dateValue <= maxDate;
});

    jQuery.validator.unobtrusive.adapters.add('dayrange', ['min', 'max', 'dateseperator'], function (options) {
        var params = {
            min: options.params.min,
            max: options.params.max,
            seperator: options.params.dateseperator
        };

        options.rules['dayRange'] = params;
        if (options.message) {
            options.messages['dayRange'] = options.message;
        }
    });
}(jQuery));

I also change the way I add the adapter to unobtrusive so I can add additional properties. Never send to server-side dev to do a front-end engineers job ;) Hope this helps someone.

like image 147
jolySoft Avatar answered Sep 20 '22 11:09

jolySoft


Reference: http://bradwilson.typepad.com/blog/2010/10/mvc3-unobtrusive-validation.html

adapters.addMinMax()'s param is orderby this:

adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute

so you need this:

jQuery.validator.unobtrusive.adapters.addMinMax('dayrange', '', '', 'dayrange','minlength', 'maxlength');

AND,,,

param.min, param.max be sure to undefine. param is an purely array as: ['111','000'].

so you need:

var minDate = now.setDate(now.getDate() - param[0]);
var maxDate = now.setDate(now.getDate() + param[1]);
like image 22
zicjin Avatar answered Sep 20 '22 11:09

zicjin