我想到了一种解决方案。您可以添加新PhaseListener
的,它将在 beforePhase 方法中查找PhaseEvent
并PhaseId = RENDER_RESPONSE
在其内部编写如下内容:
public class MyPhaseListener implements PhaseListener {
private void findKeyValuePairInTree(UIComponent root,
Map<String, String> map) {
if (root instanceof HtmlOutputLabel) {
map.put(((HtmlOutputLabel) root).getFor(),
((HtmlOutputLabel) root).getValue());
}
if (root.getChilder() != null && !root.getChildren().isEmpty()) {
for (UIComponent child : root.getChilder()) {
findKeyValuePairInTree(child, map);
}
}
private HashMap<String, String> idToLabelMap= new HashMap<String,String>();
public void beforePhase(PhaseEvent event) {
if (event.getPhaseId().equals(PhaseId.RENDER_RESPONSE) {
findKeyValuePairInTree(FacesContext.getCurrentInstance().getViewRoot(),
idToLabelMap);
// after above function finished execution in idToLabelMap will be all
// pairs of component ID used in standard FacesMessage as key
// and HtmlOutputLabel value attr used as value
Set<String> keySet = idToLabelMap.keySet();
for(String key : keySet) {
Iterator messages = FacesContext.getCurrentInstance().getMessages(key);
while (iterator.hasNext) {
FacesMessage msg = (FacesMessage) iterator.next();
// now replace all occurences of clientId with label value from map
msg.setSummary(msg.getSummary().replaceAll(key, idToLabelMap.get(key)));
msg.setDetails(msg.getDetails().replaceAll(key, idToLabelMap.get(key)));
}
}
FacesContext.getCurrentInstance().getMessages();
}
}
...
}
现在在此方法之后的渲染阶段,所有消息FacesContext.getCurrentInstance().getMessages()
都将clientId
随着标签值的变化而变化,并且因为验证阶段在渲染阶段之前,所有验证都将通过或失败 - 不再有来自验证的消息。
唯一的问题是,当您在实例的for
属性中使用HtmlOutputLabel
相同的 id 两次或更多时,因为在不同的形式中可以使用相同的 id 用于组件。然后你可以在for
attr 里面<h:outputLabel>
使用更复杂的 id,例如用表单 id 或类似的东西来提示它。