This is a quick tip for something that I just tried with an ASP.NET MVC app and that worked as expected.
I use MVC Foolproof Validation to complement the standard validators that come with ASP.NET MVC in the System.ComponentModel.DataAnnotations assembly. Foolproof has some awesome validators like:
[Is] [EqualTo] [NotEqualTo] [GreaterThan] [LessThan] [GreaterThanOrEqualTo] [LessThanOrEqualTo]
[RequiredIf] [RequiredIfNot] [RequiredIfTrue] [RequiredIfFalse] [RequiredIfEmpty] [RequiredIfNotEmpty] [RequiredIfRegExMatch] [RequiredIfNotRegExMatch]
You can get it through a NuGet package here.
Let’s say you have a form with a DateTime field called “Show Until” that is part of a Notice object. This property stores a date value that should be in the future obviously. It makes no sense to set a date in the past for this field. So the question is: how can you get client side validation for this field without the need of going to the server to compare the date the user entered with today’s date?
This is what this post will show you…
This is the model property decorated with the respective data annotation GreaterThanOrEqualTo:
[Required(ErrorMessageResourceName = "Required", ErrorMessageResourceType = typeof(Localization))] [Display(Name = "ShowUntil", ResourceType = typeof(Localization))] [GreaterThanOrEqualTo("Today", ErrorMessageResourceName = "GreaterThanOrEqualTo", ErrorMessageResourceType = typeof(Localization))] public DateTime ShowUntil { get; set; }
Pay attention to that "Today", string value. It tells Foolproof’s validator to compare the ShowUntil property with a property called Today (the dependent property). Wait a moment: the Notice object doesn’t have a property called Today since it’s not necessary. What’s the point?
Now let’s add a partial class to extend the Notice class with a property called Today. This property returns Today’s date of course.
public partial class Notice { public DateTime Today { get { return DateTime.Today; } } }
Run the app now, enter a date in the past for the ShowUntil field and submit the form. You’ll see that a postback is made to the server and only after that the validation error message is shown to the user. Foolproof’s validator doesn’t know what’s the value of Today yet since it’s not part of the form data being edited. Remember: this kind of server side validation is not what we want. We want client side validation. We don’t want this data round-trip to the server just to validate one field in the form. So, how to solve this? It’s pretty simple…
Inside your form view (.cshtml file) since I’m using C# as the programming language and Razor view engine, add this hidden field:
@Html.HiddenFor(model => model.Today)
Now reload the page and try entering a date in the past like yesterday’s date. You’ll see that the user gets the validation error message instantly. Why? Because now Foolproof’s jQuery validator that is added to page has Today’s date value present in the form’s HTML output (that’s the purpose of the hidden field). If you look at the form/page source code in the browser (right click the browser window and select “View Page Source” in Firefox), you’ll se this value:
<input data-val="true" id="Today" name="Today" type="hidden" value="29/06/2012 00:00:00" />
That’s it. No date in the past is allowed when adding a new Notice to the system.
This use case can be considered a good use for Hidden fields. They serve a multitude of purposes…
Hope it helps.
Updated at 12:45 PM
You see how things are... after posting this I just discovered a really straightforward way of getting what I wanted (by chance) I can tell you. I wasn’t looking for this anymore when I hit this StackOverflow question. Looks like God took me there… I happen to be using jQuery UI Datepicker control too. It has between its vast array of options a minDate property. So if you do this:
<script type="text/javascript"> $(document).ready(function () { $("#ShowUntil").datepicker('option', 'minDate', new Date()); }); </script>
new Date() is Today in Javascript and so the datepicker won’t allow the selection of dates in the past. One word: AWESOME. One liner with jQuery help!