0

我很难解决以下问题。我的问题很简单:我想用红色突出显示触发验证错误的表单字段。使用 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 的代码无法正常工作。所有表单字段都具有相同的“id”。更让我惊讶的是:他们在 FacesContext 中也有相同的“clientId”:

contentForm:revisionDocuments:revisionSequenceAdresse

在浏览树时,我无法区分是否确实看到了正确的表单字段或其他任何表单字段。

有没有人提示解决这个问题?或者另一个建议来实现我的领域的亮点?我不得不承认,我真的不喜欢我的代码,我认为像我正在做的那样操作 viewRoot 很脏,但我想不出更好的解决方案来突出我的字段的通用亮点。

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

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

4

2 回答 2

2

您应该改为在客户端应用它。您有一组带有消息的客户端 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>,例如.

于 2011-12-09T13:32:42.743 回答
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”属性,对此我深表遗憾。

丑陋的解决方案,但有趣且有效。

于 2011-12-16T08:57:49.760 回答