Link an error message to multiple UIComponent in JSF2

浪子不回头ぞ 提交于 2019-12-06 11:29:40

问题


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...


回答1:


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:

  • JSF doesn't support cross-field validation, is there a workaround?
  • How validate two password fields by ajax?

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'}" />


来源:https://stackoverflow.com/questions/8616086/link-an-error-message-to-multiple-uicomponent-in-jsf2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!