我使用的是OmniFaces FullAjaxExceptionHandler
和PrimeFaces。我在errorPage.xhtml
中添加了一个命令按钮,如下所示:
<h:form>
<p:commandButton id="logoutButtonId" value="Redirect" actionListener="#{userMB.logout()}">
</h:form>
错误页面得到正确显示,但按钮不触发方法#{userMB.logout()}
。以下是我所理解的设置:
- 如果发生错误,
FullAjaxExceptionHandler
将显示errorPage.xhtml
。 - 如果我点击我添加的按钮,页面会用相同的数据更新,就像刷新一样。
- 如果我再次点击按钮,则触发托管bean方法。
只有在第二次单击时才调用bean方法。似乎在第一次加载时,bean方法没有绑定到对象。
在使用FullAjaxExceptionHandler
时,如何实现在错误页面中添加一个命令按钮,并将action/actionlistener正确绑定到HTML组件?
这就是对我有效的方法,结合了BalusC在下面的回答中提到的方法。它可以在IE和Firefox中工作。在某些情况下,它可能需要一些调整,但由于我得到的错误页面只有一个表单,所以我没有费心遍历表单。
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);
}
};
这个问题有两个可能的原因:
-
如果您使用的是Internet Explorer,那么这将被识别为PrimeFaces
@all
,无法在基于IE的浏览器中初始化必要的ajax javascript。 对象不支持此属性或方法的primefaces omnifaces超时组合。 如果您正在使用另一个浏览器,并且您正在使用JSF标准
<f:ajax>
来触发ajax操作,那么这可以识别为JSF自己的jsf.js
,在@all
之后无法更新所有形式的JSF视图状态。
请注意,这些脚本需要放在调用ajax操作的页面上,而不是放在错误页面上。