Setting a Time Form Field with a JQuery DatePicker with an ASP.NET DataList in an UpdatePanel

Sometimes you will want to do something very specific on a Web page using a combination of popular technologies. However the interaction of client and server-side languages such as JQuery and ASP.NET can become confusing, especially when the server side language starts adding client-side functionality such as through an UpdatePanel control.

In this article I’m going to review a very specialized case. Here are the key points that I want the code to handle:

  1. I have an ASP.NET DataList that is showing rows of information.
  2. One column of repeating information in the DataList contains a separate Date and Time component
  3. The footer of the DataList is being used to add new rows of information, including a Date and a Time field
  4. The editable time field should display a JQuery DatePicker widget
  5. When a date is selected on the JQuery DatePicker widget, the current time should be set to a separate text field that is beside the Date field
  6. The DataList is running inside an UpdatePanel control to only refresh the DataList when Server communications happens
  7. The DataList has an edit button which the user can press to make a row editable. This involves a refresh of the DataList so that JQuery has to know to re-attach the DatePicker control to the newly editable date field

This is a lot of functionality to cover in one article and I hope it is clear for you to understand how I want the JQuery to interact with the ASP.NET. To further explain things I will give some example code of both the JQuery and the markup tags of the DataList, and I will explain how to address the requirements step-by-step.

Before I start into in-depth explanations in this article, I’d like to mention that if you are interested in reading more about ASP.NET, please check out my series of articles covering ASP.NET development. I also have written a very interesting series of articles about using JQuery to add functionality to your pages that is worth taking a look at.

Adding a Footer that Acts as an Insert Row to an ASP.NET DataList

Since the ASP.NET DataList control does not support insert functionality out of the box, the simplest way to make it do so is to add a row of editable fields along with an insert button inside of the footer row of the DataList. Then in the header markup of the DataList, set the footer row to always show. Now you have working Insert functionality in your DataList.

As an example of how you go about doing this, to set your footer row to always show, set the ShowFooter attribute to true in the header of your DataList:

<asp:DataList ShowFooter="true"

Then in your footer to add an editable date and an editable time field is pretty straightforward. Note that we also assign CSS classes to the date and time field since we will use the CSS class to identify the date fields that need to be assigned to the DatePicker widget. In the footer below we assign two CSS classes for clarity. This is done due to the DataList asynchronous postback that can take place, so we need to clearly tell JQuery to continue to support the DatePicker widget in the footer even after the object has reloaded. Here is the example footer:

<FooterTemplate>
 <td valign="top">
 ... add some columns
 </td>
 <td valign="top">
 <asp:TextBox ID="txtDateTimeUpdateDtA" runat="server" Text="" Width="70" CssClass="1CssDateTimeUpdateDt 2CssDateTimeUDT" ></asp:TextBox>
 <asp:TextBox ID="txtDateTimeUpdateTimeA" runat="server" Text="" Width="50" CssClass="1CssDateTimeUpdateTime 2CssDateTimeTime"></asp:TextBox>
 </td>
 <td valign="top" align=center ><asp:Button ID="btnDateTimesAddA" Text="Add" runat=server CommandName="DoInsert" /></td>
 <td valign="top" align=center ></td>
 </td>
 </FooterTemplate>

I’ve highlighted the TextBox controls above. The markup in green is for the TextBox which will show our DatePicker widget, and the markup in red is for the TextBox into which we want to write the time when the Date is selected in the DatePicker widget.

Adding the Editable Row Markup to the DataList

The next step is to add the markup for our editable row in the DataList. Note that this row is not rendered when the list is first shown on our Web page. This row is only rendered after the user selects a link on the row to edit it. At that point the list posts back to itself without reloading the page since it is encapsulated in an UpdatePanel control.

The catch here is that we will need to tell our JQuery to hook up the DatePicker widget to any row being edited after the page has already rendered. For now though, here is the markup for the editable version of the DataList:

<EditItemTemplate>
<td valign=”top”>
… add some columns
</td>
<td valign=”top”>
<asp:TextBox ID=”txtDateTimeUpdateDt” runat=”server” Text=<%# DataBinder.Eval(Container.DataItem, “ShowDt”) %> Width=”70″ CssClass=”1CssDateTimeUpdateDt” ></asp:TextBox>
<asp:TextBox ID=”txtDateTimeUpdateTime” runat=”server” Text=<%# DataBinder.Eval(Container.DataItem, “ShowTime”) %> Width=”50″></asp:TextBox>
</td>
<td valign=”top” align=center ><asp:Button ID=”btnDateTimesUpdate” Text=”Update” runat=server CommandName=”update” /></td>
<td valign=”top” align=center ><asp:Button ID=”btnDateTimesCancel” Text=”Cancel” runat=server CommandName=”cancel” /></td>
</td>
</EditItemTemplate>

As with the footer row example above, I have highlighted this editable row with the TextBox to show the DatePicker widget in green, and in red the TextBox into which the current time should be placed when the Date is selected.

Note that the CSS class of the TextBox that will show the DatePicker widget is the same CSS class as the TextBox in the footer that will show the DatePicker widget.

Hook Up the DatePicker Widget with the DataList When the Web Page is First Rendered

So now we get to the JQuery portion of our Web page. Our DataList is first rendering with read-only rows of repeating data (that have an edit button beside them), but with an add row in the footer. Hooking up the JQuery DatePicker widget to the Date TextBox in the DataList footer can be done with a basic setup that we are familiar with from JQuery 101:

$(document).ready(function () {
 $('.2CssDateTimeUDT').datepicker({
 dateFormat: 'yy-mm-dd' })  });

As you can see, we reference the footer TextBox using its unique CSS class id. Referencing ASP.NET objects by CSS class is a nice way of referencing DataList controls since ASP.NET will create its own tags for controls contained inside of a DataList.

Hook Up the DatePicker Widget with the DataList Row being Dynamically Edited

The next step is to hook up the DatePicker widget to any row in the DataList that a user decides to edit. Since the DataList is contained inside of an UpdatePanel control, the entire page is not refreshed when one of the DataList rows goes into edit mode. Instead we want to tell JQuery that it should watch for asynchronously loaded objects that it should associate the DatePicker control with:

$(document).ready(function () {
 Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
 function EndRequestHandler(sender, args) {
 $('.1CssDateTimeUpdateDt').datepicker({
 dateFormat: 'yy-mm-dd'});
 }
 });

This code snippet above tells JQuery when it first loads to watch for our TextBoxes that are identified by the .1CssDateTimeUpdateDt CSS class. JQuery now knows that these will appear after the page has been first loaded and after a user clicks on the edit button in one of the DataList rows to see the edit mode for that row.

* A general note for adding this request handler is that it will not identify objects when the page is first loaded. This event handler only attaches to objects on a Web page after an asynchronous event has taken place.

Populate the Time TextBox when the Date is Selected

Now that we have our DataList and have added our JQuery DatePicker control to the date fields, we want to make sure that when a user selects a date, that the current time is added to a time TextBox that is right beside the user-selected Date TextBox.

  1. The first part of the process is identifying how to add custom code to the selection event of a JQuery DatePicker widget. In the case of this example, we want to calculate the current date and add it to a TextBox when the user clicks on a calendar date. This is done in the DatePicker onClose: Event
  2. The second part of our process is to get the Id of the HTML text input area that is the time text area beside the date text area. This part of the process requires some processing logic since when ASP.NET generates a DataList, it prefixes controls inside of the DataList with the Id of the DataList and an underscore character. Then after the name of the control, ASP.NET adds an underscore and the number of the row being affected. So, the syntax for a TextBox in a DataList is: DataListId_FieldId_Row# In the case of our example the time TextBox on row2 of our DataList would be: dlDateTimeList_txtDateTimeUpdateTime_2

Here is the JQuery code that we will use to identify the row (or footer field) time TextBox to set:

  1. Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
  2. function EndRequestHandler(sender, args) {
  3. $(‘.1CssDateTimeUpdateDt’).datepicker({
  4. dateFormat: ‘yy-mm-dd’,
  5. onClose: function (selectedDate) {
  6. var currentdate = new Date();
  7. var hrs = currentdate.getHours();
  8. var mins = currentdate.getMinutes();
  9. var second = currentdate.getSeconds();
  10. var dtFieldId = this.id;
  11. var saFieldParts = dtFieldId.split(‘_’);
  12. var fieldTypeEnd = (saFieldParts[1]).charAt((saFieldParts[1]).length – 1);
  13. var setField = saFieldParts[0] + ‘_txtDateTimeUpdateTime';
  14. if (fieldTypeEnd.toLowerCase() == ‘a’) {
  15. setField += ‘A';
  16. } else {
  17. setField += ‘_’ + saFieldParts[2];
  18. }
  19. var timeField = document.getElementById(setField)
  20. timeField.value = ” + ((” + hrs).length < 2 ? ‘0’ : ”) + hrs + ‘:’ + ((” + mins).length < 2 ? ‘0’ : ”) + mins + ‘:’ + ((” + second).length < 2 ? ‘0’ : ”) + second;
  21. }
  22. });
  23. }

I’ve numbered the lines in the code above so I can explain what’s happening on each line:

In lines 1 & 2 we are telling JQuery to attach execute the subsequent code after the page has first rendered. For this example, this tells JQuery to attach itself to a Date field in our DataList after the user has clicked to edit a row.

In line 3 we associate the DatePicker control with TextBox controls that are marked with a CSS class.

Line 4 tells JQuery to format the date returned as yyyy-mm-dd I just find this format much more logical than the alternatives.

Line 5 is where we identify the onClose event of the DatePicker control. This is where we put our custom code to insert a the current time into a TextBox beside the selected Date TextBox when the user has selected a date and the DatePicker calendar is closing.

Lines 6-9 are all about getting the time component that is on the user’s machine as Hours, Minutes, Seconds

In Line 10 we get the identity of the currently selected Date TextBox using the this.id command. This is a pretty important step, and the subsequent lines are all about taking this id, splitting it apart, and re-assembling it to get the Id of the Time TextBos that we want to set.

So in line 11 we split the Date TextBox Id into a String Array by the underscore character.

In line 12 we get the last character of the Date TextBox. If it is a number we know the row being edited. If is is the character A, then we know the user is setting the footer.

Lines 13 to 18 are all about re-assembling the Id to get the Id of the footer time field or the Time TextBox of the row being edited.

In line 19 we know the Id of the Time TextBox that we want to set, and so we get a reference to it on our Web page.

In Line 20 we set the current time to the Time TextBox.

Also note that since we want our time’s to display with a 0 pre-pended if the time is a single digit, we also make sure to do this in line 20. Thus instead of writing 2:13:6 we will output the much nicer: 01:13:06

Summary

I hope I’ve been clear in this example of explaining how the various parts of the code interact. For clarity I’m giving the example code for the ASP.NET DataList and the JQuery code to manage the Date and Time setting below.

The Example DataList Control

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
 <ContentTemplate>

 <asp:DataList ShowFooter="true" ID=dlDateTimeList runat=server GridLines=Both CssClass=GridFieldLabel CellPadding=0 CellSpacing=0 OnEditCommand="dlDateTimeList_EditCommand" OnCancelCommand="dlDateTimeList_CancelCommand" OnUpdateCommand="dlDateTimeList_UpdateCommand" OnItemCommand="dlDateTimeList_ItemCommand" OnItemDataBound="dlDateTimeList_ItemDataBound">
 <HeaderStyle BackColor=Blue></HeaderStyle>
 <HeaderTemplate >
 <td align=center >... add some columns</td>
 <td align=center ><label>Updated</label></td>
 <td align=center ><label></label></td>
 </HeaderTemplate>
 <ItemTemplate>
 <td>
 ... add some columns
 </td>
 <td>
 <asp:Label ID="Label10" runat=server Text=<%# DataBinder.Eval(Container.DataItem, "ShowDt") %> Width="100"></asp:Label> 
 <asp:Label ID="Label12" runat=server Text=<%# DataBinder.Eval(Container.DataItem, "ShowTime") %> Width="100"></asp:Label>
 </td>
 <td align=center ><asp:Button ID="btDateTimesnEdit" Text="Edit" runat=server CommandName="Edit" /></td>
 <td valign="top" align=center >Spaceholder for cancel command in edit mode</td>
 </ItemTemplate> 
 <EditItemTemplate>
 <td valign="top">
 ... add some columns
 </td>
 <td valign="top">
 <asp:TextBox ID="txtDateTimeUpdateDt" runat="server" Text=<%# DataBinder.Eval(Container.DataItem, "ShowDt") %> Width="70" CssClass="1CssDateTimeUpdateDt" ></asp:TextBox>
 <asp:TextBox ID="txtDateTimeUpdateTime" runat="server" Text=<%# DataBinder.Eval(Container.DataItem, "ShowTime") %> Width="50"></asp:TextBox>
 </td>
 <td valign="top" align=center ><asp:Button ID="btnDateTimesUpdate" Text="Update" runat=server CommandName="update" /></td>
 <td valign="top" align=center ><asp:Button ID="btnDateTimesCancel" Text="Cancel" runat=server CommandName="cancel" /></td>
 </td>
 </EditItemTemplate>
 <FooterTemplate>
 <td valign="top">
 ... add some columns
 </td>
 <td valign="top">
 <asp:TextBox ID="txtDateTimeUpdateDtA" runat="server" Text="" Width="70" CssClass="1CssDateTimeUpdateDt 2CssDateTimeUDT" ></asp:TextBox>
 <asp:TextBox ID="txtDateTimeUpdateTimeA" runat="server" Text="" Width="50" CssClass="1CssDateTimeUpdateTime 2CssDateTimeTime"></asp:TextBox>
 </td>
 <td valign="top" align=center ><asp:Button ID="btnDateTimesAddA" Text="Add" runat=server CommandName="DoInsert" /></td>
 <td valign="top" align=center ></td>
 </td>
 </FooterTemplate>
 </asp:DataList> 

 </ContentTemplate>
 </asp:UpdatePanel>

The Example JQuery Code to Set Dates and Times

The first JQuery function sets the DatePicker control to the editable Date field in the DataList’s Footer Row. The second function sets the JQuery DatePicker control to rows in the DataList that the user has clicked to edit and/or the footer row after a refresh of the DataList control.

<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.1/themes/base/jquery-ui.css" />
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.1/jquery-ui.js"></script>
<script type="text/javascript" >
 $(document).ready(function () {
 $('.2CssDateTimeUDT').datepicker({
 dateFormat: 'yy-mm-dd',
 onClose: function (selectedDate) {
 var currentdate = new Date();
 var hrs = currentdate.getHours();
 var mins = currentdate.getMinutes();
 var second = currentdate.getSeconds();
 var dtFieldId = this.id;
 var saFieldParts = dtFieldId.split('_'); 
 var fieldTypeEnd = (saFieldParts[1]).charAt((saFieldParts[1]).length - 1);
 var setField = saFieldParts[0] + '_txtDateTimeUpdateTime';
 if (fieldTypeEnd.toLowerCase() == 'a') {
 setField += 'A';
 } else {
 setField += '_' + saFieldParts[2];
 }
 var timeField = document.getElementById(setField)
 timeField.value = '' + (('' + hrs).length < 2 ? '0' : '') + hrs + ':' + (('' + mins).length < 2 ? '0' : '') + mins + ':' + (('' + second).length < 2 ? '0' : '') + second;
 }
 });
 Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
 function EndRequestHandler(sender, args) {
 $('.1CssDateTimeUpdateDt').datepicker({
 dateFormat: 'yy-mm-dd',
 onClose: function (selectedDate) {
 var currentdate = new Date();
 var hrs = currentdate.getHours();
 var mins = currentdate.getMinutes();
 var second = currentdate.getSeconds();
 var dtFieldId = this.id;
 var saFieldParts = dtFieldId.split('_'); 
 var fieldTypeEnd = (saFieldParts[1]).charAt((saFieldParts[1]).length - 1);
 var setField = saFieldParts[0] + '_txtDateTimeUpdateTime';
 if (fieldTypeEnd.toLowerCase() == 'a') {
 setField += 'A';
 } else {
 setField += '_' + saFieldParts[2];
 }
 var timeField = document.getElementById(setField)
 timeField.value = '' + (('' + hrs).length < 2 ? '0' : '') + hrs + ':' + (('' + mins).length < 2 ? '0' : '') + mins + ':' + (('' + second).length < 2 ? '0' : '') + second;
 }
 });
 }
 });
 </script>

One thought on “Setting a Time Form Field with a JQuery DatePicker with an ASP.NET DataList in an UpdatePanel

  1. Pingback: Setting a Time Form Field with a JQuery DatePicker with an ASP.NET DataList in an UpdatePanel | JQuery-Features | Scoop.it

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s