p:wizard 和 autoUpdate 设置为 true 的消息组件

p:wizard and message components with autoUpdate set to true

A <p:wizard> 需要在执行最后一步后在 <p:messages> and/or <p:growl> 上显示消息,然后返回第一步,如下所示(向导执行三个步骤)。

<h:form id="form">
    <p:messages id="message" for="message" redisplay="false" showDetail="true" autoUpdate="true"/>

    <p:wizard widgetVar="wizard">
        <p:tab title="Tab 1"></p:tab>
        <p:tab title="Tab 2"></p:tab>

        <p:tab title="Tab 3">
            <p:commandButton process="@this"
                             oncomplete="alert('Message'); PF('wizard').loadStep(PF('wizard').cfg.steps[0], true)"
                             value="Submit"
                             actionListener="#{bean.action}"/>
        </p:tab>
    </p:wizard>
</h:form>

托管 bean:

@Named
@ViewScoped
public class Bean implements Serializable {

    private static final long serialVersionUID = 1L;

    public Bean() {}

    public void action() {
        FacesMessage message = new FacesMessage();
        message.setSeverity(FacesMessage.SEVERITY_INFO);
        message.setSummary("Message Summary");
        message.setDetail("Message from backing bean");
        FacesContext.getCurrentInstance().addMessage("message", message);
    }
}

bean中的action()方法中设置为messageFacesMessage出现的时间很短,然后突然消失(在本例中,我通过在两者之间添加一个警告框来暂停它)。

罪魁祸首是 <p:commandButton>oncomplete 处理程序中的 JavaScript 代码。

PF('wizard').loadStep(PF('wizard').cfg.steps[0], true)

这会使向导从最后一步返回到第一步,导致自动更新的 <p:messages> 组件消失。

忽略自动更新(即将其设置为 false)在实际项目中不是一个选项,将 ignoreAutoUpdate 设置为 true 在这种情况下也有帮助,因为 <p:commandButton> 本身不负责执行此任务。

如何防止该代码更新 <p:messages> 组件,以便它始终显示上述 message/s?


真正需要注意的是,在实际情况下,<p:messages> 被放置在 <h:body> 最开始的主模板上,目的是显示一些与抛出的异常相对应的全局消息来自服务层,如 javax.persistence.OptimisticLockException。因此,在 <p:messages> 上应用某些条件会在全局范围内影响该组件 - 需要做一些独立于 <p:messages>.

的事情

根据 PF 源代码,ignoreAutoUpdate="true" 的效果可以通过向 ajax 回发提供 primefaces.ignoreautoupdate=true 请求参数来实现。但是,我没有看到在不破解 JS 源代码的情况下将其传递给 loadStep() 函数的简单方法。

我可以想到一个解决方法,在 JS 范围内设置一些布尔值,并在 pfAjaxSend DOM 事件期间检查它,然后将所需的请求参数附加到 ajax 请求 options.data 可用的查询字符串。为了防止全局 JS 范围污染,我选择将自定义 属性 添加到全局 PrimeFaces 对象。

<p:commandButton ... oncomplete="PrimeFaces.ignoreAutoUpdate=true; PF('wizard').loadStep(PF('wizard').cfg.steps[0], true)" />
$(document).on("pfAjaxSend", function(event, xhr, options) {
    if (PrimeFaces.ignoreAutoUpdate) {
        options.data += "&primefaces.ignoreautoupdate=true";
        PrimeFaces.ignoreAutoUpdate = false;
    }
});

这种方式也可以在其他地方重复使用,只需在 ajax 回发之前在 JS 中设置 PrimeFaces.ignoreAutoUpdate=true

这种方法可能值得 PF 人员提出增强请求。