我对 p:messages 组件有疑问。
首先,这是我的配置:
然后,我的代码:
test.xhtml
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:fn="http://java.sun.com/jsp/jstl/functions">
<h:head>
<f:facet name="first">
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</f:facet>
<meta http-equiv="cache-control" content="no-store,no-cache" />
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="expires" content="0" />
</h:head>
<h:body>
<div id="content">
<h:form id="form1">
<p:tooltip/>
<p:messages id="messages" showDetail="true" />
<p:remoteCommand async="true" autoRun="true" process="@this" partialSubmit="true" action="#{testBean.checkA}" />
<p:remoteCommand async="true" autoRun="true" process="@this" partialSubmit="true" action="#{testBean.checkB}" />
</h:form>
</div>
</h:body>
</html>
Test.java
import java.io.Serializable;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import org.primefaces.context.RequestContext;
@ManagedBean(name="testBean")
@ViewScoped
public class Test implements Serializable {
private static final long serialVersionUID = -1L;
public void checkA() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,"Message 1", null));
RequestContext.getCurrentInstance().update("form1:messages");
}
public void checkB() {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN,"Message 2", null));
RequestContext.getCurrentInstance().update("form1:messages");
}
}
这段代码的功能非常简单。页面加载时,会进行两次AJAX调用(checkA和checkB)。我在checkA中放了一个Thread.sleep(2000)
用于测试目的,因为我希望它在checkB之后完成。方法完成后,会向UI发回消息。
当我加载页面时,我看到两个AJAX调用。 CheckB将首先完成,所以我会在我的页面上看到“消息2”。但是一旦checkA完成,消息被“消息1”替换。我想要做的是追加“消息1”到“消息2”,因此用户将在屏幕上看到这两条消息。有没有办法做到这一点,还是组件的限制?
其次,正如您在我的代码中所看到的,我必须致电RequestContext.getCurrentInstance().update("form1:messages");
才能看到我的p:messages
正在更新。如果我删除这行代码并将autoUpdate="true"
添加到组件中,则它不起作用...
有一件事需要考虑,遗憾的是,我无法更改服务器的配置,因为我没有管理它,并且已经有很多其他应用程序。
提前感谢您的帮助!
答案 0 :(得分:4)
您遇到的问题是FacesMessages是Request Scoped。当您执行两个ajax请求时,当您到达第二个请求时,第一个消息在此时不可用。
您使用的@ViewScoped
bean在您离开视图本身之前一直处于活动状态,因此解决方法应该是有一种堆栈/队列来存储要显示的消息。当您考虑完成上一个请求时,只需将所有消息添加到FacesContext
并清除堆栈。
其他选择是以相同的方法执行所有操作,并在此之后显示所需的消息。您会因为执行一个请求而不是两个请求而减少网络流量,但如果您想要render specific parts of the page before other ones,则您的选择似乎很有意思。
关于您的更新问题,请记住您可以直接在页面中指定要更新的表单部分。尝试将update="messages"
添加到您的p:remoteCommand
代码中。关于autoUpdate
无法正常工作,您的remoteCommand
partialSubmit
属性可能会让您遇到问题。从Primefaces docs中查看该属性的定义:
partialSubmit:启用属于部分值的序列化 仅处理过的组件。
答案 1 :(得分:1)
您可以使用多个p:message
组件:
<p:message id="message1"
for="message1ValidatorCall" />
<h:inputHidden id="message1ValidatorCall" value="message1ValidatorCall">
<f:validator validatorId="myValidator" />
</h:inputHidden>
<p:message id="message2"
for="message2ValidatorCall" />
<h:inputHidden id="message2ValidatorCall" value="message2ValidatorCall">
<f:validator validatorId="mySecondValidator" />
</h:inputHidden>
如果您想检查或验证某事,请考虑faces validators
:
@FacesValidator("myValidator")
public class MyValidator implements Validator {
@Override
public void validate(FacesContext facesContext, UIComponent uiComponent, Object o) throws ValidatorException {
//validator logic
}
}