Asp.Net Textbox with jQuery UI Datepicker value lost on a postback
In this post I am going to talk about an issue I faced while using jQuery Datepicker control wherein the datepicker was losing the date on post back. The text boxes were losing the dates even when the view state was enabled for the text boxes and/or page, unexpected.
Scenario
I was working on a web application and had to develop a form that manipulates (Creates/Edits) schedule information (Start/End Date) for a job. I had four types of schedules (Daily, Weekly, Monthly, and Quarterly). Schedules could be infinite as well wherein there will be no end-date for the schedule. The user was allowed to enter date by typing it or by selecting from datepicker. There were different client/side and server side validations I had to do on the dates input by the user.
Solution
I tried to work it out by using the alternate field feature that jQuery datepicker offers. I used hidden field to store the date selected/entered by the user. But in this approach it was tricky to keep sync between the main text box to which datepicker is attached to and the hidden field. Refer to code snippets below to find how hidden field was attached to the datepicker:
Control (ASCX) Markup
<table class="table-General">
<tr>
<td>
<asp:CheckBox ID="chkEnableMonthlyNotifications" runat ="server" CssClass="cell-Text" Text="Enable monthly notifications." />
<br/>
</td>
</tr>
<tr>
<td class="td-General">
<label for="txtMonthStartDate" class="cell-Text">Specify start date for monthly notification</label>
<br />
<br />
<asp:TextBox ID="txtMonthStartDate" runat="server" Enabled="true"></asp:TextBox>
<asp:HiddenField ID="hdnMonthStartDate" runat="server" />
</td>
</tr>
<tr>
<td class="td-General">
<label for="txtMonthEndDate" class="cell-Text">Specify end date for monthly notification, or leave blank if no end date.</label>
<br />
<br />
<asp:TextBox ID="txtMonthEndDate" runat="server" Enabled="true" >
</asp:TextBox>
<asp:HiddenField ID="hdnMonthEndDate" runat="server" />
</td>
</tr>
</table>
jQuery to Initialize Datepicker with Alternate Field
$(document).ready(function () {
$("[id$=_txtMonthStartDate]").datepicker({ showOn: 'button', buttonImageOnly: true, buttonImage: '/icon_cal.png', altField: '[id$=_hdnMonthStartDate]' });
$("[id$=_txtMonthEndDate]").datepicker({ showOn: 'button', buttonImageOnly: true, buttonImage: '/icon_cal.png', altField: '[id$=_hdnMonthEndDate]' });
$("[id$=_txtQuarterStartDate]").datepicker({ showOn: 'button', buttonImageOnly: true, buttonImage: '/icon_cal.png', altField: '[id$=_hdnQuarterStartDate]' }); $("[id$=_txtQuarterEndDate]").datepicker({ showOn: 'button', buttonImageOnly: true, buttonImage: '/icon_cal.png', altField: '[id$=_hdnQuarterEndDate]' }); $("[id$=_txtHalfYearStartDate]").datepicker({ showOn: 'button', buttonImageOnly: true, buttonImage: '/icon_cal.png', altField: '[id$=_hdnHalfYearStartDate]' }); $("[id$=_txtHalfYearEndDate]").datepicker({ showOn: 'button', buttonImageOnly: true, buttonImage: '/icon_cal.png', altField: '[id$=_hdnHalfYearEndDate]' }); $("[id$=_txtYearStartDate]").datepicker({ showOn: 'button', buttonImageOnly: true, buttonImage: '/icon_cal.png', altField: '[id$=_hdnYearStartDate]' });
$("[id$=_txtYearEndDate]").datepicker({ showOn: 'button', buttonImageOnly: true, buttonImage: '/icon_cal.png', altField: '[id$=_hdnYearEndDate]' });
}
To avoid difficulties to keep the two fields in sync as the user plays with the date field, I tried to set the date picker value again on “document.ready” after the post back. I did the following:
1) Checked if the text box has the attribute called “Value” present.
2) If the attribute is present I checked if it has some value which the user entered/selected before postback.
3) If the value is there I used jQuery datepicker API option called “setDate” to initialize the datepicker again with the value user entered. Refer to the jQuery snippet below:
jQuery Code to set Datepicker date again
$(document).ready(function () {
//Initializing the datepicker
$("[id$=_txtMonthStartDate]").datepicker({ showOn: 'button', buttonImageOnly: true, buttonImage: '/icon_cal.png', altField: '[id$=_hdnMonthStartDate]' });
//Code to set the datepicker's date again after post back
if(!($("[id$=_txtMonthStartDate]").attr("Value") == undefined))
{
if($("[id$=_txtMonthStartDate]").attr("Value").length > 0)
{
$("[id$=_txtMonthStartDate]").datepicker("setDate",new Date($("[id$=_txtMonthStartDate]").val($("[id$=_txtMonthStartDate]").attr("Value"))));
}
}
}
This solved the problem and datepickers did not lose the value after post backs.
jQuery selectors can be optimized by using dynamically generated control Id or by using jQuery selector that selects element based on a CSS class.