我很难解决以下问题。我的问题很简单:我想用红色突出显示触发验证错误的表单字段。使用context.addMessage(...)行将错误消息正确放置在FacesContext中。
我希望我的系统是通用的。所有附有消息的表单字段都会自动突出显示。
我在本网站上找到了这篇优秀文章的链接: http://www.jroller.com/mert/entry/how_to_find_a_uicomponent
有了它,我确实为RENDER_RESPONSE阶段实现了一个PhaseListener,它执行以下操作:
@Override
public void beforePhase(PhaseEvent event) {
// get context
FacesContext context = event.getFacesContext();
// iterate on all the clientIds which have messages
Iterator<String> clientIdsWithMessages = context.getClientIdsWithMessages();
while (clientIdsWithMessages.hasNext()) {
// get the clientId for the field component
String clientIdWithMessage = clientIdsWithMessages.next();
// split on ":"
String[] splitted = clientIdWithMessage.split(":");
UIComponent component = findComponentInRoot(splitted[splitted.length - 1]);
if (component != null) {
Map<String, Object> attributes = component.getAttributes();
if (attributes.containsKey("style")) {
attributes.remove("style");
}
attributes.put("style", "background-color: #FFE1E1;");
}
}
}
这几乎适用于我的所有用途。
现在,它变得有点棘手,是我的一些表单有这样的代码:
<ice:dataTable id="revisionDocuments" value="#{agendaBean.agenda.revisionsDocuments}" var="revision">
<ice:column>
<ice:inputText value="#{revision.sequenceAdresse}" id="revisionSequenceAdresse" />
</ice:column>
....
生成的表单有几行(revisionsDocuments列表的每个对象一行),每个元素都有一个唯一的标识符(clientId),如下所示:
contentForm:revisionDocuments:0:revisionSequenceAdresse
每次迭代为0改为1,2,.... 因此,从ViewRoot搜索UIComponent所提供的代码无法正常工作。所有表单字段都具有相同的&#34; id&#34;。让我更加惊讶的是:他们拥有相同的&#34; clientId&#34;在FacesContext中也是:
contentForm:revisionDocuments:revisionSequenceAdresse
在穿过树时,我无法区分,如果我确实看到了正确的表格字段或任何其他字段。
有人有提示要解决这个问题吗?或者另一个建议来实现我的领域的亮点?我不得不承认,我真的不喜欢我的代码,我认为操作viewRoot很脏,就像我做的那样,但是我无法想出一个更好的解决方案来获得我的字段的一般亮点。
我在JBOss AS 7.0.2.Final上使用JSF-Impl 2.1.1-b04运行IceFaces 2.0.2。
提前感谢您的答案。 最好的祝福, 帕特里克
答案 0 :(得分:2)
您应该在客户端应用此功能。您有一组带有消息的客户端ID。其中一种方法是将此信息传递给JavaScript并让它完成工作。您可以在本文中找到此类PhaseListener
的示例:Set focus and highlight in JSF。
从JSF 2.0开始,不需要PhaseListener
就可以采用另一种方式。有一个新的隐式EL变量#{component}
,它引用当前组件的UIComponent
实例。如果是UIInput
个组件,则会有isValid()
个方法。这允许您执行以下操作:
<h:inputText styleClass="#{component.valid ? '' : 'error'}" />
在CSS文件中使用:
.error {
background: #ffe1e1;
}
(是的,您也可以在style
属性中执行此操作,但使用标记混合样式是一种不好的做法)
要抽象出来(这样你就不需要在每个输入中重复它),你可以为此创建一个composite component,类似于<my:input>
。
答案 1 :(得分:0)
为了完整性,这里是我最终发现的解决方案,突出显示有IceFaces 2.0.2错误消息的字段:
基本思想与BalusC在http://balusc.blogspot.com/2007/12/set-focus-in-jsf.html
提出的建议完全相同我必须使用IceFaces更改的代码是一个小的Javascript调用:
<script>
setHighlight('${highlight}');
</script>
我找不到任何在每次JS调用时重新渲染的IceFaces组件。我发现将脚本放入panelGroup大部分时间都可以工作。但是,有一个案例不起作用:
提交有错误的表单会触发JS。 然后,重新提交与先前验证相同的字段上的错误表单不会触发JS。 然后,重新提交任何错误字段没有更多错误的表单会触发JS。 然后,重新提交带有错误的任何非错误字段的表单会触发JS。
出于某种原因,当两个调用之间有错误的字段集相同时,IceFaces不会呈现包含JS的panelGroup。
我尝试将Javascript API与Ice.onAsynchronousReceive()等代码一起使用,使用Prototype库将事件附加到commandButton的AJAX完成,但是没有取得多大成功。我的一些测试可以运行(有错误但是完成了工作),我可以观察到类似的行为。
这是我最终使用的技巧(丑陋但有效):
<ice:panelGroup>
<script type="text/javascript">
var useless = '#{testBean.time}';
setHighlight('${highlight}');
</script>
</ice:panelGroup>
getTime()函数只返回当前时间戳。然后,该值始终不同,并在任何AJAX请求时触发JS执行。
可悲的是,IceFaces没有RichFaces有用的“oncomplete”属性,我对此案感到非常遗憾。
丑陋的解决方案,但有趣且有效。