Problem
As was mentioned in a previous blog I am building a web page that allows the user to select dates in a calendar and then shows the dates in an unordered list. The problem now is that those dates need to be sent to the server on page submit so that they can be saved to the database. If I was storing the dates in an input element, say a textbox, that wouldn't be an issue but because they are in an html element whose contents are not posted to the server an alternative strategy needs to be developed.
Solution
The approach that I took to solve this problem is as follows:
1. Place a hidden input field on the form
<input id="hiddenDates" name="hiddenDates" type="hidden" value="" />
ASP.Net MVC has an Html helper with a method called Hidden() that will do this for you @Html.Hidden("hiddenDates").
2. Copy the values from the html element to the hidden input field before submitting the form
The following javascript is added to the page:
$(function () {
$('#formCreate').submit(function () {
PopulateHiddenDates();
});
});
function PopulateHiddenDates() {
var dateValues = '';
$($('#dateList').children('li')).each(function(index) {
dateValues += $(this).attr("id") + ",";
});
$('#hiddenDates').val(dateValues);
}
I'm using jQuery to bind to the form submit event so that my method to populate the hidden field gets called before the form is submitted. The dateList element is an unordered list and by using the jQuery each function I can itterate through all the <li> items that it contains, get each items id attribute (to which I have assigned the value of the date in millisecs) and write them to the hidden field as a comma delimited string.
3. Process the dates on the server
[HttpPost]
public ActionResult Create(string hiddenDates, string utcOffset)
{
List<DateTime> dates = GetDates(hiddenDates, utcOffset);
}
private List<DateTime> GetDates(string hiddenDates, int utcOffset)
{
List<DateTime> dates = new List<DateTime>();
var values = hiddenDates.Split(",".ToCharArray(),StringSplitOptions.RemoveEmptyEntries);
foreach (var item in values)
{
DateTime newDate = new DateTime(1970, 1, 1).AddMilliseconds(double.Parse(item)).AddMinutes(utcOffset*-1);
dates.Add(newDate);
}
return dates;
}
By declaring a parameter with the same name as the hidden field ASP.Net will take care of finding the corresponding entry in the form collection posted back to the server and binding it to the hiddenDates parameter! Excellent! I now have my dates the user selected and I can save them to the database. I have also used the same technique to pass back a utcOffset so that I know what timezone the user is in and I can show the dates correctly to users in other timezones if necessary (this isn't strictly necessary at the moment but I plan to introduce times later),
Saving multiple dates from an unordered list - DONE!