Search code examples
jqueryasp.net-mvcvalidationunobtrusive-validation

Unobtrusive validation/jQuery client-side Validate that Date entered is more than the current date


I have a Date field , and I would like to verify that this date is higher than today's date.

<script>
    jQuery.validator.addMethod("currentdate", function (value, element) {
        return Date.parse(value) > Date.parse(new Date());
    }, jQuery.validator.format("Date invalid"));
</script>

    @Html.LabelFor(m=>m.booking.Date)
    @Html.TextBoxFor(m => m.booking.Date, new { @class = "form-control", @id="Date" })
    @Html.ValidationMessageFor(m=>m.booking.Date)

What is the approach to take ? How do I have to structure my html helper ?


Solution

  • Assuming the following form with a text box called Date:

    @model TestFormViewModel
    
    @{
        ViewBag.Title = "Index";
        HtmlHelper.ClientValidationEnabled = true;
        HtmlHelper.UnobtrusiveJavaScriptEnabled = true;
    }
    
    <h2>Test Form</h2>
    
    @using (Html.BeginForm())
    {
        @Html.TextBoxFor(x => x.Date)
        @Html.ValidationMessageFor(x => x.Date)
        <input type="submit" value="Submit" />
    }
    
    @section scripts {  
        <script src="~/Scripts/jquery-1.10.2.js"></script>
        <script src="~/Scripts/jquery.validate.js"></script>
        <script src="~/Scripts/jquery.validate-vsdoc.js"></script>
        <script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
        <script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
        <script src="~/Scripts/validationrule.js"></script>
    }
    

    Simple controller action:

    [HttpPost]
    public ActionResult Index(TestFormViewModel requestResponsemodel)
    {
        return View(requestResponsemodel);
    }
    

    A JavaScript file included into the page called validationrule.js:

    $.validator.unobtrusive.adapters.add("currentdate", [], function (options) {
        options.rules['currentdate'] = options.params;
        if (options.message) {
            options.messages['currentdate'] = options.message;
        }
    });
    
    $.validator.addMethod("currentdate",
        function (value, element, other) {
    
            return Date.parse(value) > Date.parse(new Date());
        }
    );
    

    DateValidationAttribute.cs containing your server side validation:

    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
    public class CurrentDateValidationAttribute : ValidationAttribute, IClientValidatable
    {
    
        // Default error message, can be overridden in the use of the attribute on your model
        public CurrentDateValidationAttribute() : base("The date must be later than the current date.")
        {
        }
    
        public override bool IsValid(object value)
        {
            var dateToValidate = (DateTime)value;
            return dateToValidate > DateTime.UtcNow;
        }
    
        // Client-Side validation 
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientCurrentDateValidationRule("The date must be later than the current date.");
            yield return rule;
        }
    }
    

    ... and a ModelClientValidationRule that will put the error message into the output of your Html helper (@Html.TextBoxFor()) to be picked up on the client side by your JavaScript validation code:

    public class ModelClientCurrentDateValidationRule : ModelClientValidationRule
    {
        public ModelClientCurrentDateValidationRule(string errorMessage)
        {
            ErrorMessage = errorMessage;
            ValidationType = "currentdate";
        }
    }
    

    The model to validate with the custom validation attribute assigned to your model, in this case the Date property:

    public class TestFormViewModel
    {
        [CurrentDateValidation(ErrorMessage = "The date must be later than the current date.")]
        public DateTime Date { get; set; }
    }
    

    Your date field will validate on the client site as invalid when the date contained in the field is before the current date, like so:

    validation for field before the current date