Alleviating client-side back-button issues with Ajax4JSF and RichFaces
November 8, 2007
Recently an article I wrote was published on the Seam conversation model and how issues with the back-button can be eliminated through a continuation approach. This aids developers in resolving back-button issues with respect to server-side state, but what about the client-side. Ajax development is a breeze with Seam especially when used in conjunction with Ajax4JSF and RichFaces but the use of Ajax can result in issues with caching of client-side state.
Caching is a common issue with Ajax implementations though many of the concerns of caching are alleviated by using the Ajax4JSF/RichFaces libraries (which I highly recommend). The specific problem I would like to address applies to use of Internet Explorer with Ajax (Firefox does not suffer from the problem). Internet Explorer caches pages when the entire page is refreshed. Ajax implementations allow the page to be altered without a refresh, only re-rendering the applicable section of the page. Thus, if a user submits a page or navigates elsewhere, using the back- or forward-button to return to the page will not display any portions of the page that had been updated by Ajax calls. Instead the page will be shown based on what was cached when the page was originally rendered. Firefox, on the other hand, maintains an up-to-date cache that displays the page as it was rendered after any AJAX updates in response to interaction with the user.
If you don’t believe me, try it yourself! Go to maps.google.com and view a map of your favorite location using Internet Explorer. Now type a new URL into your browser and navigate to it. Press the back button and *poof* you’re back at square one. The map of your favorite location is gone. Now perform the same steps using Firefox. Wow, Firefox still shows the map and you can still see your favorite location!
This is a rather annoying issue and of course could lead to issues with our conversation state (not to mention confusion of the users). Not to fear, the issue can be resolved through a fairly simple solution. Internet Explorer invokes the onload function every time a page is displayed (whether through the initial rendering, the back-, or the forward- button). The following code will resolve your issue using Ajax4JSF which ships with JBoss RichFaces:
<body bgcolor="#FFFFFF" text="#000000"
onload="reloadAjaxPanels()">
<h:form id="myAjaxForm">
<a:jsFunction name="reloadAjaxPanels"
reRender="panelToReload" />
...
<a:outputPanel id="panelToReload">
...
</a:outputPanel>
</h:form>
Now each time the user backs up to the page the Ajax panels will be updated according to the state of the current conversation. The downsides to the solution are that the user will notice a flash each time he or she backs up to the page (when the Ajax components reload) and it causes (what I would consider unnecessary) traffic between the client and the server. If this is acceptable, this solution will help you to use Ajax and Seam together to allow applications to behave according to a user’s expectations rather than the developer’s.








Posted in
content rss
December 10th, 2007 at 4:47 am
Great follow-up. I didn’t notice that you had started blogging but I caught this link in the trackback to the original article. I posted about it so it’s findable in the Dev Fu categories.
December 10th, 2007 at 2:54 pm
Thanks Karsten
January 5th, 2008 at 9:37 am
It is so helpfull. Thx!!!
January 28th, 2008 at 1:30 pm
I considered using your approach but I ended up using a client side only solution. I added an oncomplete attribute to the a4j:commandLinks that I was using to update the page.
In this method, I saved a copy of the dynamically update section to a hidden input field.
function saveAjaxSection() {
var currentContent = document.getElementById( "tdrContentRegion" ).innerHTML ;
document.getElementById( "ajaxSaveField" ).value = currentContent ;
}
Then when the page reloads, I restore that section by hooking into the window.onload event and have it call the method below:
function reloadAjaxPanels(){
var previousContent = document.getElementById( "ajaxSaveField" ).value ;
if ( previousContent.length > 0 ) {
document.getElementById( "tdrContentRegion" ).innerHTML = previousContent ;
}
document.getElementById( "tdrContentRegionWrapper" ).style.display = "inline" ;
};
January 28th, 2008 at 1:34 pm
I forgot to mention that I also got rid of the “flash” of old content by making that section initially hidden and then enabling it in the window.onload. So both of the “downsides” that you mentioned get eliminated.
January 28th, 2008 at 6:27 pm
John,
Very nice option. The only downside I see is having to create hidden inputs for all sections that need to be reloaded, but in general cases this should be manageable. Thanks for sharing your approach!
April 4th, 2008 at 7:22 am
i have the same problem after try this code.
i am using richface 3.2.0 GA and seam 2.0.1.GA
this is my cample code
this code like a data Tabe filter .
After filter the data table by using Checkbox at the top , visit to the next page then i hit the browser back button , my filter list will be deselected .
how to resolve this problem.
we have this problem in our site. we need to fix this bug.
by
Thiagu.m
April 5th, 2008 at 2:45 pm
Discussion on Seam forum
April 24th, 2008 at 5:24 am
At the risk of sounding like an idiot, John talks about hooking into the window.onload… How do I do that? I don’t have direct access to as I’m using facelets templating and don’t see how I can add the onload attribute to my page without affecting all other pages.
April 24th, 2008 at 5:29 am
Oh, and the problem I’m having is that I have a search page (form fields and search results list) I navigate to one of the search results, hit the back button and all my fields are empty as well as my search results. I’ve confirmed that my backing beans are still alive as certain events on the page trigger reloads of the ajax components - suddenly restoring the fields. The difference I have with what you’ve described here is that it isn’t limited to IE, it’s also happening in firefox. So perhaps this indicates I’ve got other problems.