如何使用PrimeFaces消息组件堆叠消息?

Nas*_*o47 7 ajax jsf messages primefaces

我有一个关于p:messages组件的问题.

首先,这是我的配置:

  • PrimeFaces:4.0.3(精英)
  • JSF:MyFaces 2.0.2
  • 服务器:WebSphere 8.5.0.2

然后,我的代码:

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>
Run Code Online (Sandbox Code Playgroud)

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");
   } 
}
Run Code Online (Sandbox Code Playgroud)

这段代码的功能非常简单.页面加载时,会进行两次AJAX调用(checkA和checkB).我已经把Thread.sleep(2000)checkA用于测试目的,因为我希望它在checkB之后完成.方法完成后,会向UI发回消息.

当我加载页面时,我看到两个AJAX调用.CheckB将首先完成,所以我会在我的页面上看到"消息2".但是一旦checkA完成,消息被"消息1" 替换.我想要做的是 "消息1" 附加到"消息2",以便用户在屏幕上看到这两个消息.有没有办法做到这一点,还是组件的限制?

其次,正如你在我的代码中看到的那样,我必须打电话RequestContext.getCurrentInstance().update("form1:messages");才能看到我p:messages的更新.如果我删除这行代码并添加autoUpdate="true"到组件,它不起作用...

有一件事需要考虑,遗憾的是,我无法更改服务器的配置,因为我没有管理它,并且已经有很多其他应用程序.

在此先感谢您的帮助!

Xtr*_*ica 4

您遇到的问题是 FacesMessages 是Request Scoped。当您执行两个 ajax 请求时,当您到达第二个请求的末尾时,第一条消息此时不可用。

您使用的@ViewScopedbean 在您离开视图本身之前一直保持活动状态,因此解决方法应该是有一种堆栈/队列来存储要显示的消息。当您认为最后一个请求已完成时,只需将所有消息添加到FacesContext并清除堆栈即可。

其他选择是以相同的方法执行所有操作,然后显示您想要的消息。由于执行一个请求而不是两个请求,您会减少网络流量,但如果您想在其他请求之前渲染页面的特定部分,您的选择似乎很有趣。

关于您的更新问题,请记住您可以直接在页面中指定要更新的表单部分。尝试添加update="messages"到您的p:remoteCommand标签中。关于autoUpdate不工作,可能是您remoteCommandpartialSubmit属性给您带来了问题。从Primefaces 文档中查看该属性的定义:

partialSubmit:仅允许序列化属于部分处理的组件的值。

  • 我已经成功创建了一个简单的向量,用作我的消息的缓冲区,并且它工作得很好。感谢您的帮助! (2认同)