Building Interactive User Interfaces with Microsoft ASP.NET AJAX: Rebinding Client-Side Events After a Partial Page PostbackBy Scott Mitchell
The UpdatePanel is the workhorse of the ASP.NET Ajax library. It is responsible for defining regions of a web page that trigger partial page postbacks (as opposed to full page postbacks). Such partial page postbacks transfer less information between the client and server and have their user interfaces updated seamlessly, thereby leading to a more interactive user experience. (For more information on UpdatePanels, refer to Using the UpdatePanel.) One side-effect of a partial page postback is that the HTML elements within the UpdatePanel are replaced with the markup returned on postback. This behavior is not noticeable and is not an issue unless you have client-side event handlers wired up to the elements within the UpdatePanel. Such client-side event handlers are lost after a partial page postback.
blur events, which "highlights" the TextBox when the user focuses it and unhighlights it when losing focus. Initially, this
script works as expected - clicking on the TextBox will "highlight" it. However, things break down once the Button is clicked. When the Button is clicked the UpdatePanel
triggers a partial page postback and submits an asynchronous HTTP request back to the server. The requested ASP.NET page then goes through its life-cycle again, but this time
only the markup in the UpdatePanel (and the hidden form fields on the page) are returned to the browser. The UpdatePanel then overwrites its existing markup with the
markup just returned from the server. Unfortunately, this overwriting obliterates the
blur client-side event handlers, meaning that
selecting the TextBox no longer highlights it.
In short, if there are client-side event handlers attached to HTML elements within an UpdatePanel it is imperative that they be rebound after a partial page postback. This article looks at three different ways to accomplish this. Read on to learn more!
Exploring the Problem
As noted in the introduction, client-side event handlers for HTML elements in an UpdatePanel are lost after a partial page postback. In this article we'll identify three different approaches for overcoming this obstacle, but before we do let me take a moment to explain the problem we are trying to solve in more detail to make sure we are all on the same page. (The code samples provided here are taken from a sample application I built, which you can download at the end of this article.)
<script> element above
starts by referencing the file where this library exists (
~/Scripts/jquery-1.4.2.min.js). Next, the script defines two event handler functions named
UnhighlightFormField, which add and remove the
highlightFormField CSS class from the HTML element that
raised the event. The
$(document).ready event handler, which fires after the browser has loaded the DOM, wires up the all textboxes (
drop-down lists (
select) and multi-line textboxes (
blur events to the
UnhighlightFormField event handlers, respectively.
highlightFormField CSS class applied. The
highlightFormField CSS class (not shown here) indicates a light-yellow background color and a dashed border. The screen shot below shows the page
when visited through a browser and after clicking on the first textbox, which now appears highlighted.
In the above user interface there is a DropDownList that asks the user if they want to receive the newsletter. If the user chooses Yes we might want to show a textbox to collect their email address. This could be done by adding a Panel to the page that contains a TextBox control to collect the email address.
Next, the DropDownList control's
AutoPostBack property would need to be set to True so that we could determine when the DropDownList was modified and display
(or hide) the email Panel accordingly. We'd also create a server-side event handler for the DropDownList's
SelectedIndexChanged event that would show or hide
the Panel as needed.
With the above modifications everything would continue to work as expected presuming that the user interface was not in an UpdatePanel. If changing the DropDownList's
value caused a full postback to fire then changing the DropDownList would reload the entire page. On postback the
$(document).ready event handler would
execute and the client-side event handlers to highlight the form fields on the page would be established.
However, if we put the above user interface within an UpdatePanel then things break down. When the page is first visited the
$(document).ready event handler
executes and creates the client-side event handlers - selecting a textbox highlights it as expected. But when the user makes a selection from the drop-down list there would
be a partial page postback. On partial page postback, the UpdatePanel overwrites its existing markup with the markup returned from the server (which now includes the
textbox for the user's email address), but doing so severs the client-side event handlers. Consequently, after a partial page postback the form fields are no longer
highlighted upon selection.
So how do we correct this behavior? In short, we need the client-side event handlers to be reestablished after the partial page postback completes. There are many ways this can be accomplished. Let's look at three such ways.
endRequest Event Handler
In Performing Client Actions in Response to Partial Page Postbacks, a previous article in this series, we learned that whenever a partial page postback is triggered the
PageRequestManagerobject manages the interaction, from dispatching the HTTP request back to the server to receiving to response and updating the user interface. During the life-cycle of a partial page postback, the
PageRequestManagerobject performs the following client-side actions:
initializeRequestevent is raised - this is the first event raised during the partial postback life-cycle and affords us an opportunity to determine the HTML element that triggered the postback and cancel the postback, if needed.
beginRequestevent is raised - this event is raised just before the request is sent to the server. The UpdateProgress control uses this event to displayed it's output.
- The request is sent to the server and the page is re-rendered there.
pageLoadingevent is raised when the server returns its response.
pageLoadedevent is raised. This event is raised whenever the content on the page is refreshed, be it via a full page postback or a partial page postback.
endRequestevent is raised, signalling completion of the partial page postback lifecycle.
endRequestevent is raised, signalling the completion of the partial page postback. After the partial page postback has completed the UpdatePanel's user interface has been overwritten and the client-side event handlers that were associated with the HTML elements in that user interface have been lost. This, then, is a great time to add those event handlers back in.
To accomplish this we need to do two things:
- Move the code that adds the client-side event handlers to the page's textboxes and drop-down lists from the
$(document).readyevent handler to a new function (let's call it
WireUpFormFields). We then need to call this new function from
- Create an event handler for the
endRequestevent that calls the
Here's the updated
<script> tag that goes in the
<head> section. Note that the client-side event wiring code has been moved to a new
WireUpFormFields, and that the
$(document).ready event handler calls this function.
Next, we need to have the
WireUpFormFields function called whenever the
endRequest event fires. This code must appear after the
ScriptManager control, so don't put it in the
<head> section. Instead, add this
<script> block at the end of the page (or anywhere
else after the ScriptManager control).
Using the UpdatePanel's Server-Side
Load Event Handler
As we just saw, when a partial page postback occurs a number of client-side events fire. There are also server-side events that fire. For example, on each request to the web page - whether its the initial visit, a partial page postback, or a full page postback - the UpdatePanels on the page have their
Loadevents fire. We can create a server-side
The code for the UpdatePanel's
Load event handler would look similar to the following. Note that I am using the
WireUpFormFields client-side function."
If you are using jQuery, as I did in these examples, there's an even easier approach - the
live()function defines an event handler for one or more HTML elements now or in the future. What that means is that you can say things like, "Hey, jQuery, I want you to affix this event handler to the
clickevent of any
<a>element on the page, whether it exists now or at some future point." Consequently, if an
<a>element is dynamically added to the page at a later time, jQuery will automatically wire up its
clickevent to the specified event handler.
For our purposes we want to wire up the
UnhighlightFormField event handlers to the
events of the textboxes and drop-down lists on the page now or in the future. The "in the future" part ensures that after a partial page postback, when the original
textboxes and drop-down list are replaced with new ones, those new form fields will automatically be configured to have the client-side event handlers we had initially
defined when the page was first loaded.
live() function is pretty straightforward - just specify the event name (as a string) and the event handler, as the following script shows:
live() function is probably the easiest and most intuitive approach, but it presumes that you are using jQuery. If you are not using jQuery you'll
need to rely on one of the two other techniques covered in this article.
pageLoad()are not the same!