h:body 在使用 FullAjaxExceptionHandler 时没有重新渲染

bar*_*kae 6 jsf omnifaces

我正在使用 OmniFaces FullAjaxExceptionHandler来显示错误页面。错误页面显示正确,但这些页面的样式有问题。

我的应用程序使用的模板在 body 元素上定义了 CSS 类。这些类对于正常页面和错误页面是不同的:

普通页面:

<h:body styleClass="main-body layout-compact">
Run Code Online (Sandbox Code Playgroud)

错误页面:

<h:body styleClass="exception-body error-page">
Run Code Online (Sandbox Code Playgroud)

当 FullAjaxExceptionHandler 处理异常时,会执行到错误页面的转发(基于 中的<error-page>机制web.xml)。显然这不会重新渲染<h:body>标签,因为在检查 HTML 输出时,我可以看到<body>标签仍然包含来自普通页面的 CSS 类(而不是错误页面的类)。

看来原来<h:body>的内容被错误页面的内容替换了,<h:body>而不是仅仅替换了完整的<h:body>. 我不知道这是否是默认的 JSF / FullAjaxExceptionHandler 行为。

有什么方法可以<h:body>使用正确的 CSS 类进行渲染?将 CSS 类移开<h:body>不是一种选择。

Bal*_*usC 5

不幸的是,这是“设计使然”。JSF 在执行 ajax 导航时不会替换整个文档,但它只会替换个体<head><body>元素的子级,而保持父级不变。这样做是出于历史原因;较旧的 Internet Explorer 版本即不支持完全替换它们。

我自己所做的只是简单地将样式放入<main>元素中。的<header><footer>是在最终的HTML输出通常是相同的反正。基本上:

<html>
    <head>
        <title>...</title>
    </head>
    <body>
        <header>...</header>
        <main class="#{page.type}">...</main>
        <footer>...</footer>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

如果您确实需要<body class>修改,那么最好的办法是通过嵌入在错误页面模板中的 JavaScript 来进行。

<h:outputScript rendered="#{faces.ajaxRequest}">
    document.body.className = "exception-body error-page";
</h:outputScript>
Run Code Online (Sandbox Code Playgroud)

注意:#{faces}仅自 OmniFaces 2.5 起可用,如果您使用旧版本,请改用#{facesContext.partialViewContext.ajaxRequest})。