JSF2 + IceFaces 2 -从viewwroot中检索ui组件



我很难解决以下问题。我的问题很简单:我想用红色突出显示触发验证错误的表单字段。使用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

1, 2,…对于每个迭代。因此,提供的用于从ViewRoot中搜索ui组件的代码不能正常工作。所有表单字段都有相同的"id"。更让我惊讶的是:他们在FacesContext中也有相同的"clientId":

contentForm:revisionDocuments:revisionSequenceAdresse

在遍历树时,我无法区分是否看到了正确的表单字段或其他字段。

有没有人有一个提示来解决这个问题?或者另一个建议来实现我的字段的亮点?我必须承认,我真的不喜欢我的代码,我认为操纵视图很脏,但我想不出一个更好的解决方案,让我的字段有一个通用的高亮。

我在JBOss AS 7.0.2.Final上运行IceFaces 2.0.2和JSF-Impl 2.1.1-b04。

提前感谢您的回答。最好的问候,帕特里克。

您应该在客户端应用它。您已经获得了一组带有消息的客户端id。其中一种方法是将此信息传递给JavaScript并让它完成工作。您可以在本文中找到这样一个PhaseListener的示例:在JSF中设置焦点和高亮。

自从JSF 2.0以来,有另一种不需要PhaseListener的方法。有一个新的隐式EL变量#{component},它指的是当前组件的UIComponent实例。在UIInput组件的情况下,有一个isValid()方法。这允许您执行如下操作:

<h:inputText styleClass="#{component.valid ? '' : 'error'}" />
在CSS文件中使用

:

.error {
    background: #ffe1e1;
}

(是的,您也可以在style属性中这样做,但是将样式与标记混合在一起是一种糟糕的做法)

要将其抽象出来(这样您就不需要在每个输入中重复它),您可以为此创建一个复合组件,如<my:input>

为了完整,下面是我最终找到的解决方案,突出显示在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库将事件附加到命令按钮的AJAX完成,但没有太大的成功。我的一些测试可以运行(有错误,但完成了工作),我可以观察到类似的行为。

这是我最后使用的技巧(丑陋但有效):
<ice:panelGroup>
    <script type="text/javascript">
        var useless = '#{testBean.time}';
        setHighlight('${highlight}');
    </script>
</ice:panelGroup>

getTime()函数只是返回当前时间戳。该值总是不同的,并在任何AJAX请求时触发JS执行。

遗憾的是,IceFaces没有RichFaces有用的"oncomplete"属性,我对这种情况感到非常遗憾。

丑陋的解决方案,但有趣和工作。

最新更新