Creating a Popup Date Picker

By Conrad Jalali

Prerequisites
  • Familiarity with C#, Visual Studio .NET, and creating ASP.NET applications
  • Basic understanding of Events in .NET
  • Basic understanding of JavaScript
  • Basic understanding of HTML

  • download source code C#
  • download source code VB .NET

Introduction

Recently, I was working on a Web Form and I wanted to give users an easy way to enter a date into a TextBox control. Back in the days of Classic ASP, I frequently used a small ASP page, opened in a popup window, to display a calendar. Users could go to the previous/next month, and when a date was clicked, the selected date would populate the input field via some basic JavaScript.

But we're in the .NET world now. I wanted to come up with an easy way to do this that would rely on the rich controls that Microsoft included with ASP.NET. After a quick trip to Google, I found a solution; add a new EventHandler to the ASP.NET Calendar control's SelectionChanged event that emits the JavaScript needed to set the value of the TextBox.

All was well in the world. I had a solution that provided the functionality that I needed, and I didn't have to use a third party control or write my own from scratch. But then I started testing the solution...

While everything worked, there was an annoying delay between the user's click selecting a date, and the date populating the TextBox. This pause, which lasted a few seconds, was driving me crazy. It didn't take long to find the culprit; the PostBack.

Even though the Calendar control was using JavaScript to set the value of the TextBox, it was doing so when the SelectionChanged event fired. This event is fired on PostBack, so there was a delay between the user's click and the data filling in the TextBox. Remember, the PostBack submits a Web Form back to itself. This causes the user to wait unnecessarily, and needlessly adds to the Web server's load.

Back to the Drawing Board

I still didn't want to create my own custom calendar control, and I wasn't satisfied with the PostBack option, so I decided to explore extending the functionality of the ASP.NET Calendar control. Specifically, the Calendar control's DayRender method piqued my interest, so I let my IntelliSense do the walking.

I found that I could clear the standard date link from each day in the calendar and create my own link. My link would include the HTML and JavaScript needed to populate the TextBox and close the popup window. Now I was in business.

Building the Solution

Let's look at the elements that will make up our solution:

  • A Web Form with a TextBox control whose value will be populated by the calendar
  • A link on the Web Form with some JavaScript to launch the date picker popup
  • A Web Form for the date picker popup
  • A Calendar control on the date picker page with an extra DayRenderEventHandler attached
  • A DayRenderEventHandler delegate to replace the standard date links with a custom JavaScript link

The Web Form is straight forward:


Figure 1

Here is the HTML for the "pick" link, which launches the date picker popup:

<a href="javascript:;" onclick="calendarPicker('Form1.txtEventDate');" title="Pick Date from Calendar">pick</a>

Note that since the tag does not have the runat="server" attribute, the onClick event will fire on the client-side (in the browser), not on the server.

As you can see, the link calls a JavaScript function called, calendarPicker. I prefer to call a function with the link, rather than writing the code in-line, as there may be more than one date field on a form. If we write the code in a function that uses a parameter to specify the reference to the field that we want to set, we can reuse the code for as many TextBox controls as we like on a single page. We can also debug JavaScript functions, but more on that, later.

I like to pass the calendarPicker function the name of the field that we want to edit in the format, "FormName.FieldName". You might have occasion to substitute your own form ID for VS .NET's standard "Form1", so I don't like to hard code this.

Here is the calendarPicker function:

<script language="javascript" type="text/javascript">

/// <summary>

/// Launches the DatePicker page in a popup window,

/// passing a JavaScript reference to the field that we want to set.

/// </summary>

/// <param name="strField">String. The JavaScript reference to the field that we want to set,

/// in the format: FormName.FieldName

/// Please note that JavaScript is case-sensitive.</param>

function calendarPicker(strField)

{

window.open('DatePicker.aspx?field=' + strField, 'calendarPopup', 'width=250,height=190,resizable=yes');

}

</script>

The calendarPicker function opens a page called DatePicker.aspx in new window. It passes the name of the field that we want the calendar to set in the QueryString. I like to use Visual Studio-style comments for my client-side scripts since it gets me in the habit of documenting my code.

Next, the DatePicker ASPX page:


Figure 2

The DatePicker page contains one standard ASP.NET Calendar control:

<%@ Page language="c#" Codebehind="DatePicker.aspx.cs" AutoEventWireup="false" Inherits="CalendarPopup.DatePicker" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >

<html>

<head>

<title>DatePicker</title>

<meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">

<meta name="CODE_LANGUAGE" content="C#">

<meta name="vs_defaultClientScript" content="JavaScript">

<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">

<style type="text/css">

BODY { PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 4px; PADDING-TOP: 0px }

BODY { FONT-SIZE: 9pt; FONT-FAMILY: Verdana, Geneva, Sans-Serif }

TABLE { FONT-SIZE: 9pt; FONT-FAMILY: Verdana, Geneva, Sans-Serif }

TR { FONT-SIZE: 9pt; FONT-FAMILY: Verdana, Geneva, Sans-Serif }

TD { FONT-SIZE: 9pt; FONT-FAMILY: Verdana, Geneva, Sans-Serif }

</style>

</head>

<body onblur="this.window.focus();" ms_positioning="FlowLayout">

<form id="Form1" method="post" runat="server">

<div align="center">

<asp:calendar id="Calendar1" runat="server" showgridlines="True" bordercolor="Black">

<todaydaystyle forecolor="White" backcolor="#FFCC66"/>

<selectorstyle backcolor="#FFCC66"/>

<nextprevstyle font-size="9pt" forecolor="#FFFFCC"/>

<dayheaderstyle height="1px" backcolor="#FFCC66"/>

<selecteddaystyle font-bold="True" backcolor="#CCCCFF/>

<titlestyle font-size="9pt" font-bold="True" forecolor="#FFFFCC" backcolor="#990000"/>

<othermonthdaystyle forecolor="#CC9966"/>

</asp:calendar>

</div>

</form>

</body>

</html>

The BODY tag contains a simple script that runs in the onBlur event (clientside) to turn the popup into a modal dialog box. Since we want the popup to be small, and its only purpose is to set a field value in the main page, there's no reason to let the user switch back to the other window.

The magic happens in a method that we attach to the Calendar's DayRender event:

/// <summary>

/// Replaces the standard post-back link for each calendar day

/// with the javascript to set the opener window's TextBox text.

/// Eliminates a needless round-trip to the server.

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void Calendar1_DayRender(object sender, System.Web.UI.WebControls.DayRenderEventArgs e)

{

// Clear the link from this day

e.Cell.Controls.Clear();

 

// Add the custom link

System.Web.UI.HtmlControls.HtmlGenericControl Link = new System.Web.UI.HtmlControls.HtmlGenericControl();

Link.TagName = "a";

Link.InnerText = e.Day.DayNumberText;

Link.Attributes.Add("href", String.Format("JavaScript:window.opener.document.{0}.value = \'{1:d}\'; window.close();", Request.QueryString["field"], e.Day.Date));

// By default, this will highlight today's date.

if(e.Day.IsSelected)

{

Link.Attributes.Add("style", this.Calendar1.SelectedDayStyle.ToString());

}

 

// Now add our custom link to the page

e.Cell.Controls.Add(Link);

}

This method will be called each time the Calendar control renders a day. The first thing that our method does is clear the contents of the table cell for the day that's being rendered. Next, we programmatically create a hyperlink (an <A> tag). We use the current day number from the Calendar as the InnerText for the link, just like the Calendar control would normally have done. We set the "HREF" property of the link by building a string that has the JavaScript needed to set the value of the TextBox control in the opener window, and then close the DatePicker window.

In the JavaScript, "opener" is a keyword that refers to the window that opened the current window via a window.open command. ASP.NET TextBox controls are renedered as <INPUT> tags in HTML. The script continues by setting the value of the particular field that we want to change, and in this case, we're specifying that the selected date be used (formatted with the ShortDatePattern) to set the value of the field.

In our Calendar1_DayRender method, we then check to see if the day that we're on represents today's date. Since we haven't specified the Calendar's SelectedDate property, it will select today's date by default. I like to give users a reference point, so I add a "style" attribute to our link and use the Calendar's SelectedDayStyle.

We wrap everything up by inserting our replacement hyperlink in the table cell for the day that we're on.

Things are going along fine, but we still haven't re-wired the Calendar control to call our custom method. To attach Calendar1_DayRender to the DayRender event for the Calendar, we can either edit DatePicker.aspx in Design mode in VisualStudio .NET or directly modify the page's InitializeComponent method in the code-behind file.

To avoid messing with the auto-generated code in the InitializeComponent method, we can add the EventHander by viewing the DatePicker page in Design mode. Click on the Calendar control and then click on the Events icon (the lightning bolt) in the Properties box. We should be able to select the method, Calendar1_DayRender, in the drop down menu next to the DayRender action.

VS .NET populates the available choices in the drop down menu by searching the code-behind file for any methods that match the ASP.NET Calendar control's DayRender event delegate signature. (The DayRenderEventHandler delegate takes two parameters; an object and a DayRenderEventArgs type.)


Figure 3

If we prefer to attach the custom delegate ourselves (or simply want to take a look at the changes made through the VS.net IDE), we can find the InitializeComponent method in the code-behind file in a region labeled "Web Form Designer generated code".

/// <summary>

/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InitializeComponent()

{

this.Calendar1.DayRender += new System.Web.UI.WebControls.DayRenderEventHandler(this.Calendar1_DayRender);

this.Load += new System.EventHandler(this.Page_Load);

}

Notice that we're adding our DayRenderEventHandler, not replacing the Calendar control's built-in EventHandler. This is indicated by the += syntax. Let's let ASP.NET do the work of creating the HTML table for the calendar, and all of the days in the month. We're just going to substitute our own content for each day's table cell.



Downloads

Comments

  • yooooooooooooooo

    Posted by keru on 05/23/2014 09:47pm

    you does not provide proper code with example

    Reply
  • paul cruz outlet Paul Smith wallet which get a high review from your customers.

    Posted by HooveHonKeype on 05/18/2013 07:46pm

    低コスト hotsaleの [url=http://www.oakleysunglassesya.com/]オークリー サングラス[/url] 安いオークリーレーダー [url=http://www.oakleysunglassesya.com/]オークリー ゴーグル[/url] セレクションなサン [url=http://www.oakleysunglassesya.com/]オークリー アウトレット[/url] グラスオレンジフレーム多 [url=http://www.oakleysunglassesya.com/]www.oakleysunglassesya.com/[/url] オークリー アウトレット 色 [url=http://www.oakleysunglassesja.com/]オークリー アウトレット[/url] コンタクトレンズ!、当 [url=http://www.oakleysunglassesja.com/]オークリー サングラス[/url] 社のウェブサイトを [url=http://www.oakleysunglassesja.com/]Oakley サングラス[/url] 選択してください 格安オー [url=http://www.oakleysunglassesja.com/]www.oakleysunglassesja.com/[/url] オークリー サングラス クリーレーダー詰め合わせ [url=http://www.raybansunny.com/]サングラス rayban[/url] なサングラスオレンジフ [url=http://www.raybansunny.com/]ray-ban サングラス[/url] レーム多色レンズ優れた [url=http://www.raybansunny.com/]レイバン サングラス[/url] 取得す [url=http://www.raybansunny.com/]www.raybansunny.com/[/url] ray-ban サングラス る良質最高品質リー [url=http://www.raybanshop2013.com/]Rayban サングラス[/url] ズナブルな価格で最高品質。もっ [url=http://www.raybanshop2013.com/] レイバン サングラス[/url] と安くオークリーレーダー [url=http://www.raybanshop2013.com/] レイバン メガネ[/url] レンジなサングラスオレ [url=http://www.raybanshop2013.com/]www.raybanshop2013.com/[/url] レイバン メガネ ンジフレーム多色お問い合わせあなたが買 [url=http://www.seikowatchkan.com/]セイコー 時計[/url] うには、あなたが取得は得ることが [url=http://www.seikowatchkan.com/]セイコー 腕時計[/url] できます!今卸売にアクション [url=http://www.seikowatchkan.com/]セイコー ウオッチ[/url] を取るビッグ格安オークリーレーダ [url=http://www.seikowatchkan.com/]www.seikowatchkan.com/[/url] セイコー 腕時計 ーの品質セレクションなサングラスオレンジフレーム多色手頃な価格オークリーレーダー範囲なサングラスレモンフレーム多色レンズ問い合わせ、あなたの素晴らしい格安スタート遠足!

    Reply
  • Finding the ASP.NET Client ID to Avoid Hard Coding

    Posted by Mike on 10/25/2012 06:35am

    Adding onto Steve's note for the content place holders...rather than searching the page for the client ID, I made the initial javascript call the following to dynamically find the client ID of the control: pick

    Reply
  • A little offended..

    Posted by IAM on 08/23/2012 06:51am

    I'm a little offended by this.. I'm sure it's relevant to asp developers or whatever, but when I clicked the link from Google, I was redirect through a pay-per-view ad site, and then, after you earned money from my clicking your google link, only then did I discover that this is about asp.net and not actually about the bit of javascript i was looking for. I'm adding this to my personal blocklist.

    Reply
  • Make the Date Picker show the current date that is in the textbox

    Posted by Steve on 06/26/2012 05:59am

    Modify the page script thus: window.open('DatePicker.aspx?field=' + strField + '&date;=' + document.getElementById(strField).value, 'calendarPopup',...... And add this to the Page Load event of the Date Picker: Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load Dim ThisDate As String = Request("date") If IsDate(ThisDate) Then Calendar1.SelectedDate = CDate(ThisDate) : Calendar1.VisibleDate = CDate(ThisDate) End Sub

    Reply
  • Does not work with MasterPages

    Posted by Steve on 06/26/2012 05:11am

    Excellent solution, but it does not work if you use MasterPages because the "real" ID of the text box is modified and hidden from you. Instead of this: [removed]window.opener.document.{0}.value Use this: [removed]window.opener.document.getElementById('{0}').value And then you need to call the Date Picker using this format: onclick="calendarPicker('ctl00_ContentPlaceHolder1_txtEventDate');" (assuming you use the default "ContentPlaceHolder1" name). If necessary, use View Source on the page to see what your text box ID is really called. Also, note this line is missing a quote mark:

    Reply
  • Enhance only dates from a database

    Posted by lironhallak on 02/26/2012 04:17am

    Hello, I want to read dates from an access database and enhance only those dates on the popup date picker you suggested. What do you think the best method for this is?

    Reply
  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • CentreCorp is a fully integrated and diversified property management and real estate service company, specializing in the "shopping center" segment, and is one of the premier retail service providers in North America. Company executives travel a great deal, carrying a number of traveling laptops with critical current business data, and no easy way to back up to the network outside the office. Read this case study to learn how CentreCorp implemented a suite of business continuity services that included …

Most Popular Programming Stories

More for Developers

RSS Feeds