6

I'm using the OmniFaces FullAjaxExceptionHandler to display error pages. The error pages are shown correctly, but I'm having issues with the styling of those pages.

My application is using a template which has CSS classes defined on the body element. These classes are different for normal and error pages:

Normal page:

<h:body styleClass="main-body layout-compact">

Error page:

<h:body styleClass="exception-body error-page">

When the FullAjaxExceptionHandler processes an exception, a forward to the error page is performed (based on the <error-page> mechanism in web.xml). Apparently this does not rerender the <h:body> tag, because when checking the HTML output, I can see that the <body> tag still contains the CSS classes from the normal page (instead of the classes of the error page).

It seems that the content of the original <h:body> is replaced with the content of the error page <h:body> instead of just replacing the full <h:body>. I don't know if this is default JSF / FullAjaxExceptionHandler behaviour.

Is there any way to have the <h:body> rendered with the correct CSS classes? Moving the CSS classes away from <h:body> is not an option.

baraskae
  • 95
  • 5
  • When you do a forward to error page, then its not an ajax call, so you can not do rerender. Instead you are loading a new whole new error page. Please check if the forward is done correctly. If so, you will have the correct CSS applied on the body tag. – OTM Apr 05 '17 at 07:57
  • The forward is done correctly by the FullAjaxExceptionHandler, I'm not doing a forward by myself. The error page is shown (under the same url) and the whole content is changed. The tag however, still has the CSS classes from the previous page. So it seems that the body tag is not rerendered, but just its contents. I don't know if this is standard JSF behaviour. – baraskae Apr 05 '17 at 08:18

1 Answers1

5

This is unfortunately "by design". JSF doesn't replace the entire document when performing ajax navigation, but it only replaces the children of individual <head> and <body> elements, leaving the parents untouched. This is done so for historical reasons; older Internet Explorer versions namely doesn't support replacing them altogether.

What I have done myself is to simply put the style into the <main> element instead. The <header> and <footer> are usually identical anyway in the final HTML output. Basically:

<html>
    <head>
        <title>...</title>
    </head>
    <body>
        <header>...</header>
        <main class="#{page.type}">...</main>
        <footer>...</footer>
    </body>
</html>

If you really need to have the <body class> modified, then your best bet is to do so via JavaScript embedded in the error page template.

<h:outputScript rendered="#{faces.ajaxRequest}">
    document.body.className = "exception-body error-page";
</h:outputScript>

Note: #{faces} is only available since OmniFaces 2.5, if you're using an older version, use instead #{facesContext.partialViewContext.ajaxRequest}).

BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
  • 1
    Thank you for the, once again, enlightening answer BalusC! As moving the styling away from the body is not possible in our case, your proposed solution using embedded JavaScript is working like a charm! – baraskae Apr 05 '17 at 09:29