如果消息出现两次,则意味着您要么由两个组件触发相同的验证器,要么验证器被触发一次但隐式地将消息添加到另一个组件。
我了解您希望将这两个组件都标记为无效(以便它们突出显示)并且您只需要一条消息。在这种情况下,您需要确保验证器被触发一次,并且另一个组件正在检索空/空消息。
您只需要更改验证器即可将整个组件检索为属性而不是其值(注意:我同时相应地编辑了旧文章;它还有另一个好处)并且您需要更改阶段侦听器以删除空/空消息。
例如在视图中:
<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 中有另一种方式来突出显示无效字段。您可以通过#{component}
EL 中的新隐式变量来做到这一点:
<h:inputText styleClass="#{component.valid ? '' : 'error'}" />