使用条件呈现

时间:2016-06-24 20:20:57

标签: ajax jsf jsf-2 primefaces

环境:JBoss EAP 6.3,Mojarra 2.1.28,JSF 2.0和java 1.7.0_79。

在我的xhtml模板上,我有两条p:消息,如下所示,用于显示全局消息:

<p:messages
    id="globalMessages"
    globalOnly="true"
    autoUpdate="true"
    severity="fatal, error, warn"
    rendered="#{menuMB.renderFatalErrorWarningMessage}" />
<p:messages
    id="globalMessagesInfo"
    globalOnly="true"
    autoUpdate="true"
    severity="info"
    rendered="#{menuMB.renderInfoMessage}" />

在MenuMB上我有

@Inject
private FacesContext facesContext;

public boolean isRenderInfoMessage() {
    return facesContext.getMaximumSeverity() == null || facesContext.getMaximumSeverity().equals(FacesMessage.SEVERITY_INFO);
}

public boolean isRenderFatalErrorWarningMessage() {
    return !isRenderInfoMessage();
}

在我使用该模板的页面上,我有几个字段及其各自的p:消息用于错误处理,例如

<h:inputText id="firstName" />
<p:message for="firstName" />

如果我在字段firstName上提交表单并且验证失败,则会按预期显示本地消息。然而,从现在开始,ajax呼叫不再起作用。

如果我将MenuMB方法更改为不使用FacesContext

public boolean isRenderInfoMessage() {
    // return facesContext.getMaximumSeverity() == null || facesContext.getMaximumSeverity().equals(FacesMessage.SEVERITY_INFO);
    return true;
}

public boolean isRenderFatalErrorWarningMessage() {
    // return !isRenderInfoMessage();
    return false;
}

,所有ajax调用都按预期继续工作。无论我是从p:messages中删除渲染选项还是设置了render = true / false(没有方法调用)。

有关如何解决这个问题的想法吗?

2 个答案:

答案 0 :(得分:0)

你可能会发现一个正在发生的异常会阻止所有未来的调用,很可能是一个潜在的java脚本问题。

同样从内存中,您不需要在呈现的标记中包装p:消息 - 它只会在您定义的指定严重性的内容中自动呈现。

带有目标渲染的gotchya是必须在页面上已经为其定位的值,因此定位可能无法渲染的属性将失败。最好将sed属性包装在你可以定位的另一个标签中,然后它将加载内部内容渲染。

答案 1 :(得分:0)

我找到解决问题的唯一方法是从primefaces重写类MessagesRenderer:

package xx.xx.xx.PFMessagesRenderer;

import org.primefaces.component.messages.MessagesRenderer;

public class PFMessagesRenderer extends MessagesRenderer {
    @Override
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
        Messages uiMessages = (Messages) component;
        ResponseWriter writer = context.getResponseWriter();
        String clientId = uiMessages.getClientId(context);
        Map<String, List<FacesMessage>> messagesMap = new HashMap<String, List<FacesMessage>>();

        ////////////////////////////////////////
        // BEGIN CHANGES
        ////////////////////////////////////////
        boolean showInfoMessage = true;

        if (uiMessages.isGlobalOnly()) {
            Iterator<FacesMessage> messages = context.getMessages(null);
            boolean hasInfoMessage = false;
            boolean hasWarnErrorFatalMessage = false;

            while (messages.hasNext()) {
                if (messages.next().getSeverity().equals(FacesMessage.SEVERITY_INFO)) {
                    hasInfoMessage = true;
                } else {
                    hasWarnErrorFatalMessage = true;
                }
            }

            if (hasInfoMessage && hasWarnErrorFatalMessage) {
                showInfoMessage = false;
            }
        }
        ////////////////////////////////////////
        // BEGIN CHANGES
        ////////////////////////////////////////

        String _for = uiMessages.getFor();
        Iterator<FacesMessage> messages;

        if (_for != null) {
            messages = context.getMessages(_for);
        } else {
            messages = uiMessages.isGlobalOnly() ? context.getMessages(null) : context.getMessages();
        }

        while (messages.hasNext()) {
            FacesMessage message = messages.next();
            FacesMessage.Severity severity = message.getSeverity();

            if (severity.equals(FacesMessage.SEVERITY_INFO)) {
                ////////////////////////////////////////
                // BEGIN CHANGES
                ////////////////////////////////////////
                if (showInfoMessage) {
                    addMessage(uiMessages, message, messagesMap, "info");
                }
                ////////////////////////////////////////
                // END CHANGES
                ////////////////////////////////////////
            } else if (severity.equals(FacesMessage.SEVERITY_WARN)) {
                addMessage(uiMessages, message, messagesMap, "warn");
            } else if (severity.equals(FacesMessage.SEVERITY_ERROR)) {
                addMessage(uiMessages, message, messagesMap, "error");
            } else if (severity.equals(FacesMessage.SEVERITY_FATAL)) {
                addMessage(uiMessages, message, messagesMap, "fatal");
            }
        }

        writer.startElement("div", uiMessages);
        writer.writeAttribute("id", clientId, "id");
        writer.writeAttribute("class", "ui-messages ui-widget", null);

        for (String severity : messagesMap.keySet()) {
            List<FacesMessage> severityMessages = messagesMap.get(severity);

            if (severityMessages.size() > 0) {
                encodeSeverityMessages(context, uiMessages, severity, severityMessages);
            }
        }

        writer.endElement("div");
    }
}

在faces-config.xml上我们需要添加

<render-kit>
    <renderer>
        <component-family>org.primefaces.component</component-family>
        <renderer-type>org.primefaces.component.MessagesRenderer</renderer-type>
        <renderer-class>xx.xx.xx.PFMessagesRenderer</renderer-class>
    </renderer>
</render-kit>

这样我的模板页面就可以有一个p:消息,如下所示:

<p:messages
    id="globalMessages"
    globalOnly="true"
    autoUpdate="true"
    severity="error, fatal, warn, info" />