3

I've been trying to integrate the jQuery UI Datepicker into our ASP.NET WebForms application. The application uses master pages to provide a common look to all pages, and all of the content pages are built inside the ContentTemplate of an UpdatePanel. I've created a user control to wrap the datepicker's functionality and allow setting of the minDate, maxDate, validators, etc. for each date from the codebehind at runtime. I also need to deal with the way ASP.NET generates client element IDs.

Over the last week, I've searched high and low, and found lots of tips for getting it to work. Here is a somewhat simplified version of where I'm at right now.

<asp:TextBox ID="txtTB" runat="server"
    MaxLength="10"
    CssClass="dateBox" />

<script type="text/javascript">

    // This function enables the datepicker behavior for this textbox by its ClientID.
    function <%=txtTB.ClientID %>() {
        $("#<%=txtTB.ClientID %>").datepicker({
            changeMonth: true, changeYear: true,
            showOn: 'button',
            buttonImage: "<%=Request.ApplicationPath %>/images/calendarIcon.gif",
            buttonImageOnly: true, buttonText: '', duration: '',
            onSelect: function() { }
        });
    };

    // Register the above function to execute on initial page load...
    $(document).ready(function(){ <%=txtTB.ClientID %>(); }) ;

    // ...and also after any update panel it's on has been refreshed. 
    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(<%=txtTB.ClientID %>);

</script>

I've left out the validators and some other markup that I don't think is related to the issue, but that's the meat of the user control--a textbox, and the jQuery script that enables the datepicker functionality. The basic idea is to leverage ASP.NET's client IDs to:

  1. Provide a unique function name for the JavaScript function for this specific control
  2. Register that function with jQuery to enable the datepicker after the initial page load
  3. Register that same function with ASP.NET's PageRequestManager to keep the datepickers enabled after postbacks

Items 1 and 2 are working great. However, after a postback, the datepicker functionality is lost and I'm left with just a textbox.

But wait! That's not all. A given page consists of multiple panels, only one of which is visible at a time. These are selected by only having the Visible property true for the current panel. The Visible property for all of other panels are set to false.

Now get this: The datepickers on the first panel, the one displayed upon initial page load, work as expected. Those on the second panel just don't show up. Going back to the first page, the datepickers show up again.

Does anyone have any ideas where I'm going wrong?

JeffK
  • 3,019
  • 2
  • 26
  • 29
  • Have you verified that the function is running and running for the right control after updatepanel refresh? – Chetan S Dec 31 '09 at 21:16
  • I've never figured out how to get javascript debugging to work right, so I can't confirm that it is. However, using Fiddler, I can see that the script for the appropriate controls is being delivered along with the refresh. I'm trying out your other suggestion now... – JeffK Dec 31 '09 at 21:56

9 Answers9

10

While $(document).ready() is ideal for one-time initialization routines, it leaves you hanging if you have code that needs to be re-run after every partial postback. The LiveQuery functionality added in jQuery v1.3+ helps with this, but only works for a limited set of functionality.

For example, what if we wanted to add a jQueryUI datepicker to the TextBox in the previous example? Adding it in $(document).ready() would work great, until a partial postback occurred. Then, the UpdatePanel’s new TextBox element would no longer have the datepicker wired up to it.

<script type="text/javascript">
  function pageLoad() {
    $('#TextBox1').unbind();
    $('#TextBox1').datepicker(); 
  }
</script>

<asp:ScriptManager runat="server" />

<asp:UpdatePanel runat="server">
  <ContentTemplate>
    <asp:Button runat="server" ID="Button1" />
    <asp:TextBox runat="server" ID="TextBox1" />
  </ContentTemplate>
</asp:UpdatePanel>

This above Answer is taken from the below link. I have tested and implemented this in one of my project.

http://encosia.com/2009/03/25/document-ready-and-pageload-are-not-the-same/

Vipin
  • 126
  • 4
  • Thanks for this. The content behind that link reads like this is really the solution I'm looking for, Unfortunately, I've had to move on to other functionality for our application. When we get the current version out and start on the next release, I'll definitely revisit the datepicker and try this out. I'll mark it as "the answer" if it works. – JeffK Jan 29 '10 at 16:08
  • Yes... It's three years later! The "pageLoad()" function was the key to success for me. It executes on both the initial page load and any following postback. I was able to use a single short function like you show here in my master page, and select using a CSS class assigned to all of the textboxes I wanted to display the datepicker. This worked perfectly. Thanks. – JeffK Apr 02 '13 at 19:12
2

Sorry for the late reply.

Why not try this:

<script type="text/javascript">
function <%=txtTB.ClientID %>() {
    $("#<%=txtTB.ClientID %>").datepicker({
        changeMonth: true, changeYear: true,
        showOn: 'button',
        buttonImage: "<%=Request.ApplicationPath %>/images/calendarIcon.gif",
        buttonImageOnly: true, buttonText: '', duration: '',
        onSelect: function() { }
    });
};
$(document).ready(function(){ 
<%=txtTB.ClientID %>();
}) ;
</script>

then put the textbox in an updatepanel with the following trigger:

<asp:UpdatePanel id="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:TextBox ID="txtTB" runat="server" MaxLength="10" CssClass="dateBox" />
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="txtTB" />
</Triggers>
</asp:UpdatePanel>
DirtyD77
  • 21
  • 1
2

I think a cleaner way to do this is to use ClientScriptManager.RegisterStartupScript.

Javascript:

function initCalendar(controlId) {
    $("#" + controlId).blahblah(....
}

In your code behind (OnPreRender perhaps):

Page.ClientScript.RegisterStartupScript(this.GetType(), "SomeName", string.Format("<script>initCalendar('{0}');</script>", txtBox.ClientID));
Chetan S
  • 23,637
  • 2
  • 63
  • 78
  • I'll give this a try. Looks promising. Does this eliminate the need to do the $(document).ready(function(){ <%=txtTB.ClientID %>(); }); – JeffK Dec 31 '09 at 21:39
  • Depends on where you put the `RegisterStartupScript`. Just ensure you call it on page load and on switching tabs. Then you don't need the `$(document).ready...`. It just puts a script block at the end of your form to be executed upon parse. Obviously, jQuery and its plugins must be loaded by then. It doesn't probably work if you load them at the end of your page. – Chetan S Dec 31 '09 at 21:56
1

Well,

Here is the solution of this problem. Below link explains why the datepicker doesn't work after ajax postback and the solution to make it work within ajax.

http://jquerybyexample.blogspot.com/2010/08/jquery-datepicker-does-not-work-after.html

Mark Henry
  • 11
  • 1
0

When you set a control's Visible property to false, it doesn't get rendered at all.

That means that the Javascript inside the invisible panels did not exist when the page was first loaded.

To solve this, you can hide your panels using CSS (display: none) instead of the Visible property.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Right, I was aware of that, and thought it might be relevant, which is why I included that in my question. But I'm still not sure why the PageRequestManager doesn't run the functions to setup datepicker functionality for the user controls on the panel that **is** being rendered? Or does the broswer not "see" the new scripts for the new date controls after a postback? If that's the case, I'm going to need another approach, but using the display:none option would make my pages just huge. (They're already well over 300-400K.) – JeffK Dec 31 '09 at 23:19
0

Just Simply use bellow code in Page_Load code behind..

string DOB = Request.Form[TextBoxDOB.UniqueID];

TextBoxDOB.Text = DOB;

I implemented this and works like a charm

Prashant Kumar
  • 20,069
  • 14
  • 47
  • 63
0

Try this inside the update panel

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

        <script type="text/javascript">
        var prm = Sys.WebForms.PageRequestManager.getInstance();

        prm.add_endRequest(function() {
            var customer = document.getElementById("<%=cmbCustomers.ClientID%>").value;

            /* Jquery Functions Here*/
            $(document).ready(function() {
               ...
            });


        });
        </script>
0

if you are using update panel then don't get panic just Click here and relax. Elaborated answer

Vijay Kumbhoje
  • 1,401
  • 2
  • 25
  • 44
-1

The solution helped me. The date picher values must be in pageLoad() function inorder for the date picker to show on postbacks. Here is my working code

<script>
    var dateToday = new Date();
    var yrRange = "2000:" + (dateToday.getFullYear()); // the range is from 2003 :2016 etc etc

    //If this datepicker is not in page load , the datepicker will not show after a post back
    function pageLoad() {

        $("#<%= txtDateFrom.ClientID %>").datepicker({ showButtonPanel: true   //Use this to show the today,done and previous and next buttons on the calender
            , changeMonth: true,     //Use this to let the user select the month easily on the calender instead of using next and previous buttons
        changeYear: true
         , yearRange: yrRange
        /***********************************
         u8se these to show the max and min dates yoiu want tio show the user
         //,minDate: "-12Y"
        // , maxDate: "+1M +10D" 
        ******************************/

        // , numberOfMonths: 2                - Use this code to show more than 1 month on the calender

        /*********************
        Use the following code to show the Calender as a Icon next to the textbox.
         showOn: "button",
        buttonImage: "images/calendar.gif",
         buttonImageOnly: true,
        buttonText: "Select date"
        ******************************/                
        });

        $("#<%= txtDateTo.ClientID %>").datepicker({
            showButtonPanel: true   //Use this to show the today,done and previous and next buttons on the calender
            , changeMonth: true,     //Use this to let the user select the month easily on the calender instead of using next and previous buttons
            changeYear: true
             , yearRange: yrRange
            // minDate: -20
            // , maxDate: "+1M +10D" - u8se these to show the max and min dates yoiu want tio show the user
            //In our case
            //, maxDate: "+1Y"
            // , numberOfMonths: 2                - Use this code to show more than 1 month on the calender

            /*********************
           Use the following code to show the Calender as a Icon next to the textbox.
             ,showOn: "button",
             buttonImage: "images/icons/calendarIcon.png" ,
             buttonImageOnly: true,
            buttonText: "Select date"
           ******************************/
        });            
    }       
</script>