I was recently tasked with upgrading an existing DotNetNuke module to use jQuery for some client side functionality. The module itself was nothing special; a simple search control that returned results which could be paged through and also filtered using dropdowns at the top. Naturally it was using the typical ASP.NET postback model to refresh its data.
I started with the client side work and soon had the desired jQuery async service calls updating my UI nicely. The smoothness of jQuery really made the ugliness of the postbacks stand out, so I decided to enable partial rendering of the module in DotNetNuke. I know using UpdatePanels is considered a bad thing (see related post at Encosia for an explanation), but in this case I had tight timelines, and the improved function I felt justified the means. With a few clicks the ugly postbacks were gone and the module itself was operating much more smoothly. Until I started doing some testing that is.
When the module first loaded the first page of search results were displayed, and the jQuery popovers with service calls were working fine. But if I did anything to cause the module to postback, jQuery no longer worked. It was really puzzling. I did some research to learn more about how jQuery worked, and in particular how it works with AJAX UpdatePanels.
In a typical request:
- Page Loads
- jQuery attaches events, hides items etc
- Async Request Happens
- UpdatePanel handles the request
- Async Request Finishes essentially rebuilding the elements
jQuery has not had a chance to attach the events etc for the new items because of the async rebuild. When AJAX finishes processing the page the $(document).ready() function is not called and jQuery isn’t wired up.
I found several potential solutions which all basically centered on a common theme – by invoking an event to happen once the Ajax UpdatePanel finishes loading. The usual way this was done was by attaching this event to the Sys.Application. To do it this way, add the following script inside your update panel at the bottom of the update panel, being the last thing in the update panel to load:
1: <script type="text/javascript">
2: //load a handler to the Sys.Application
3: Sys.Application.add_load(ApplicationLoadHandler);
4: function ApplicationLoadHandler(sender, args)
5: {
6: //get the page Manager Object
7: var prm1 = Sys.WebForms.PageRequestManager.getInstance();
8: //verify state of postback
9: if (!prm1.get_isInAsyncPostBack())
10: {
11: prm1.add_endRequest(endRequest);
12: }
13: }
14: function endRequest(sender, args)
15: {
16: loadAsyncJQuery();
17: }
18: </script>
While this might be a fine solution for a regular ASP.NET application, it isn’t really workable within a DotNetNuke module. The biggest issue being that if you enable partial rendering you really don’t have access to the UpdatePanel as DNN adds it for you automagically. That problem aside, it just seems overly complicated. Luckily there is an easier way.
We need to find a way to initialize jQuery again after the AJAX is done processing. The answer lies within the AJAX Life-Cycle Events. As it turns out, any method titled pageLoad found within the scripts on a page will get hooked up to the Sys.Application.load event. A simpler approach would be to use something like the following:
1: <script type="text/javascript">
2:
3: // this function sets up jQuery on the page
4: $(document).ready(function() {
5: InitJQuery();
6: });
7:
8: // this function will be called after the UpdatePanel finishes processing and set up jQuery again
9: function pageLoad() {
10: InitJQuery();
11: }
12:
13: function InitJQuery() {
14:
15: $("a.btnCancel").click(function() {
16: $(this).parent().hide();
17: return false;
18: });
19:
20: }
21: </script>
Not only is this simpler, it also makes using jQuery within DotNetNuke a breeze.




{ 2 comments… read them below or add one }
Shawn -
I’ve been to figure this out for nearly two days. I had come to realize the jQuery scripting wasn’t rebinding to the DOM after the postback but I hadn’t figured out how to fix it.
One thing I noticed is that if you put InitjQuery() in both the ready and pageLoad events it fires twice when the page initially loads. If you just put your code in pageLoad it works like a charm.
Thanks
Nice Article. thanks Dear