3

I am using OmniFaces FullAjaxExceptionHandler and PrimeFaces. I added a command button in the errorPage.xhtml as follows:

<h:form>
    <p:commandButton id="logoutButtonId" value="Redirect" actionListener="#{userMB.logout()}">
</h:form>

The error page gets displayed properly, but the button doesn't fire the method #{userMB.logout()}. This is what I understand what happens in my setup:

  1. If an error occurs, FullAjaxExceptionHandler nicely displays errorPage.xhtml.
  2. If I click on the button I added, the page gets updated with the same data, like as if a a refresh happens.
  3. If I click on the button again, then the managed bean method is triggered.

It is only in the second click that the bean method gets called. Seems that on first load, the bean method doesn't gets bound to the object.

How do I implement adding a command button in an error page with an action/actionlistener being properly bound to an HTML component when using FullAjaxExceptionHandler?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
mutya
  • 51
  • 6
  • Hi, I see that you attempted to post a comment via an edit. This is not the way how it works here. Adding comments should be done via "add comment" link. – BalusC Jan 12 '13 at 11:28
  • @BalusC, thanks for that, am quite a newbie here. Could you please expound on "Note that those scripts needs to be placed on the page where the ajax action is invoked, not on the error page itself." My dilemma is that I want to add a button in the error page, thus the action is invoked in the error page? Thanks in advance! – mutya Jan 12 '13 at 16:46
  • The page causing the exception. Those scripts are namely supposed to be executed during the ajax exception handling. Note that each answer has also an "add comment" link. – BalusC Jan 12 '13 at 16:48
  • I could see the viewstate id in the partial response when the error page gets displayed but the hidden input does not get added despite including the script. It only gets added on the second click. What else could I be missing? – mutya Jan 12 '13 at 17:05
  • Okay, lets get it straight first. You have 2 pages: A and B. An ajax request in Page A causes the exception. Page B is the error page. The scripts should be loaded in Page A. Did you make sure that this is the case? Further information is required to naildown the problem: 1) What are you using in Page A to trigger the ajax request? `` or something from PrimeFaces? 2) Which browser are you using? IE or others? – BalusC Jan 12 '13 at 17:22
  • You described the scenario correctly. Yes, I added the scripts in Page A. 1) using Primefaces either commandLink/commandButton 2) Using firefox – mutya Jan 12 '13 at 17:37

2 Answers2

2

This problem has two possible causes:

  1. If you are using Internet Explorer, then this is recognizable as PrimeFaces @all to fail to initialize the necessary ajax javascripts in IE based browsers. This is answered here: Object doesn't support this property or method with primefaces omnifaces timeout combination.

  2. If you're using another browser and you were using JSF standard <f:ajax> to trigger the ajax action, then this is recognizable as JSF's own jsf.js to fail to update the JSF view state in all forms after an @all. This is answered here: Bug report form on error page.

Note that those scripts needs to be placed on the page where the ajax action is invoked, not on the error page itself.

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • a combination of the solutions above worked for me. Thanks for your patience in trying to understand what is happening. I tested it with IE and FF and the approach worked, I'll put it in a separate answer as the comment wont allow me a long one...sorry, new to this. – mutya Jan 13 '13 at 05:51
2

This was what worked for me, a combination of the approach mentioned by BalusC in his answer below. It works in both IE and Firefox. It might need some tweaking for some cases but since the error page I got only has one form, I didn't bother to loop thru the forms.

var originalPrimeFacesAjaxResponseFunction = PrimeFaces.ajax.AjaxResponse;
PrimeFaces.ajax.AjaxResponse = function(responseXML) {
    var newViewRoot = $(responseXML.documentElement).find("update[id='javax.faces.ViewRoot']").text();

    if (newViewRoot) {
        var viewState = $(responseXML.documentElement).find("update[id='javax.faces.ViewState']").text();

        $('head').html(newViewRoot.substring(newViewRoot.indexOf("<head>") + 6, newViewRoot.indexOf("</head>")));
        $('body').html(newViewRoot.substring(newViewRoot.indexOf("<body>") + 6, newViewRoot.indexOf("</body>")));
        if (!$('input').attr("javax.faces.ViewState")){
            var hidden = document.createElement("input");
            hidden.setAttribute("type", "hidden");
            hidden.setAttribute("name", "javax.faces.ViewState");
            hidden.setAttribute("value", viewState);
            hidden.setAttribute("autocomplete", "off");
            $('form').append(hidden);
        }
    } else {
        originalPrimeFacesAjaxResponseFunction.apply(this, arguments);
    }
};
gpl
  • 2,777
  • 1
  • 14
  • 10
mutya
  • 51
  • 6
  • hidden input with viewState also requires proper id. without it ajax requests won't work. `hidden.setAttribute("id", "javax.faces.ViewState");` – gpl May 15 '14 at 10:57