将错误消息链接到JSF2中的多个UIComponent [英] Link an error message to multiple UIComponent in JSF2

查看:80
本文介绍了将错误消息链接到JSF2中的多个UIComponent的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要提出有关JSF2的问题.我目前正在混合BalusC在他的博客中提出的两个不同的代码段:

http://balusc.blogspot.com/2007/12/set-focus-in-jsf.html

http://balusc.blogspot.com/2007/12/validator-for-multiple-fields.html

第一个让红色突出显示确实包含错误消息的字段. 第二个让验证在多个字段上执行.

我正在寻找一种方法,可以将FacesContext中的一条错误消息(不要让该消息呈现两次)链接到多个客户端ID(因为由于多个字段验证器,该消息确实涉及多个字段)

语言基础可能吗? 如果可以,我希望避免使用手工制作的系统(它应与具有请求"范围的托管Bean一起使用,验证器会将确实有错误的clientId放置到PhaseListener可以访问的List中).

预先感谢您的提示.在FacesContext上看不到与addMessage()接近的任何东西可以完成工作,但是也许有办法...

解决方案

如果消息出现两次,则意味着您要么通过两个组件都触发了相同的验证器,要么触发了验证器一次,但隐式添加了消息发送到其他组件.

我了解到您想将这两个组件都标记为无效(以便将它们突出显示),并且只需要一条消息.在这种情况下,您需要确保验证器被触发一次,并且其他组件正在检索空/空消息.

您只需要更改验证程序以将整个组件作为属性而不是其值来检索(注意:同时,我已经相应地编辑了旧文章;它还有另一个好处),并且您需要将相位侦听器更改为删除空/空消息.

例如鉴于:

<h:outputLabel for="password" value="Password" />
<h:inputSecret id="password" value="#{bean.password}" required="true">
    <f:validator validatorId="passwordValidator" />
    <f:attribute name="confirm" value="#{confirm}" />
</h:inputSecret>
<h:message for="password" styleClass="error" />

<h:outputLabel for="confirm" value="Confirm password" />
<h:inputSecret id="confirm" binding="#{confirm}" required="true" />
<h:message for="confirm" styleClass="error" />

validate()方法中

String password = (String) value;
UIInput confirmComponent = (UIInput) component.getAttributes().get("confirm");
String confirm = confirmComponent.getSubmittedValue();

if (password == null || password.isEmpty() || confirm == null || confirm.isEmpty()) {
    return; // Let required="true" do its job.
}

if (!password.equals(confirm)) {
    confirmComponent.setValid(false);
    context.addMessage(confirmComponent.getClientId(context), new FacesMessage(null));
    throw new ValidatorException(new FacesMessage("Passwords are not equal."));
}

以及在阶段侦听器中:

Iterator<String> clientIdsWithMessages = facesContext.getClientIdsWithMessages();

while (clientIdsWithMessages.hasNext()) {
    String clientIdWithMessages = clientIdsWithMessages.next();

    if (focus == null) {
        focus = clientIdWithMessages;
    }

    highlight.append(clientIdWithMessages);

    if (clientIdsWithMessages.hasNext()) {
        highlight.append(",");
    }

    Iterator<FacesMessage> messages = facesContext.getMessages(clientIdWithMessages);

    while (messages.hasNext()) {
        if (messages.next().getSummary() == null) {
            messages.remove(); // Remove empty messages.
        }
    }
}

相关:


无关与具体问题无关,JSF2中还有另一种突出显示无效字段的方法.您可以通过EL中新的隐式#{component}变量来做到这一点:

<h:inputText styleClass="#{component.valid ? '' : 'error'}" />

I'm coming with a question on JSF2. I'm currently mixing two different pieces of code proposed by BalusC on his blog :

http://balusc.blogspot.com/2007/12/set-focus-in-jsf.html

http://balusc.blogspot.com/2007/12/validator-for-multiple-fields.html

The first let highlight in red the fields that do have an error message. The second let validation be performed on multiple fields.

I'm looking for a way to have a single error message (dont want the message to be rendered twice) in the FacesContext be linked to several client ids (because the message do concern several fields due to the multiple fields validator).

Is it possible with the language basics ? If I can, I'd like to avoid a hand-made system (it should work with a managed bean with "request" scope, the validator placing the clientIds that do have an error into a List accessed by the PhaseListener).

Thanks in advance for your tips. Could not see anything close to addMessage() on FacesContext that could do the work, but maybe there is a way...

解决方案

If the message is appearing twice, then it means that you're either firing the same validator by both components or that the validator is fired once but implicitly adding the message to the other component.

I understand that you want to mark the both components as invalid (so that they get highlighted) and that you want only one message. In that case, you need to make sure that the validator is fired once and that the other component is retrieving an empty/null message.

You only need to change the validator to retrieve the whole component as attribute instead of its value (note: I've in the meanwhile edited the old article accordingly; it has another benefits) and you need to change the phase listener to remove empty/null messages.

E.g. in view:

<h:outputLabel for="password" value="Password" />
<h:inputSecret id="password" value="#{bean.password}" required="true">
    <f:validator validatorId="passwordValidator" />
    <f:attribute name="confirm" value="#{confirm}" />
</h:inputSecret>
<h:message for="password" styleClass="error" />

<h:outputLabel for="confirm" value="Confirm password" />
<h:inputSecret id="confirm" binding="#{confirm}" required="true" />
<h:message for="confirm" styleClass="error" />

and in validate() method:

String password = (String) value;
UIInput confirmComponent = (UIInput) component.getAttributes().get("confirm");
String confirm = confirmComponent.getSubmittedValue();

if (password == null || password.isEmpty() || confirm == null || confirm.isEmpty()) {
    return; // Let required="true" do its job.
}

if (!password.equals(confirm)) {
    confirmComponent.setValid(false);
    context.addMessage(confirmComponent.getClientId(context), new FacesMessage(null));
    throw new ValidatorException(new FacesMessage("Passwords are not equal."));
}

and in the phase listener:

Iterator<String> clientIdsWithMessages = facesContext.getClientIdsWithMessages();

while (clientIdsWithMessages.hasNext()) {
    String clientIdWithMessages = clientIdsWithMessages.next();

    if (focus == null) {
        focus = clientIdWithMessages;
    }

    highlight.append(clientIdWithMessages);

    if (clientIdsWithMessages.hasNext()) {
        highlight.append(",");
    }

    Iterator<FacesMessage> messages = facesContext.getMessages(clientIdWithMessages);

    while (messages.hasNext()) {
        if (messages.next().getSummary() == null) {
            messages.remove(); // Remove empty messages.
        }
    }
}

Related:


Unrelated to the concrete problem, there's in JSF2 by the way an other way to highlight invalid fields. You can do it by the new implicit #{component} variable in EL:

<h:inputText styleClass="#{component.valid ? '' : 'error'}" />

这篇关于将错误消息链接到JSF2中的多个UIComponent的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆