计算UIComponent clientID的有效方法?

时间:2009-02-12 13:36:42

标签: jsf

实际上在我的JSF应用程序中,我有这个代码来从它的id计算组件 clientId

public static String getComponentClientId(String id) {
  try {
    FacesContext fctx = FacesContext.getCurrentInstance();
    UIComponent found = getComponentWithId(fctx.getViewRoot(), id);
    if (found!=null)
      return found.getClientId(fctx);           
    else
      return null;
  } catch (Exception e) {
    return null;
  }     
}
public static UIComponent getComponentWithId(UIComponent parent, String id) {
  for (Iterator<UIComponent> chs = parent.getFacetsAndChildren(); chs.hasNext();) {
    UIComponent ch = chs.next();
    if (ch.getId().equalsIgnoreCase(id))
     return ch;     
    else {
     UIComponent found = getComponentWithId(ch, id);
     if (found!=null)
       return found;
    }
  }
  return null;
}

该方法有效,但它在视图组件树中导航,因此效率非常低,特别是在高度填充页面的情况下。我不知道有一种聪明的方法或API可以使工作变得更快/更容易吗?

1 个答案:

答案 0 :(得分:1)

不是我知道的。

很难缓存此信息,因为:

  1. UIComponent的实例与其 clientId 之间的关系可以是1:N。对于管理其子女状态的UIData等组件,这是必需的。 getClientId的返回值可能与上下文相关。
  2. UIComponent 实例的生命周期可能不会超过请求。 StateManager的某些实现可以配置为在会话中保存视图状态,在这种情况下,对象的生命周期可能更长,但使您的代码依赖于此会使其变得脆弱引入内存泄漏很容易。
  3. 视图可以是动态的。不可否认,这是一个边缘情况,但可以通过编程方式add, remove and move组件。
  4. 在尝试其他方法之前,我会证明这是一个问题。


    你没有说明你需要什么 clientId ,但我猜这是为了某种形式的JavaScript支持。考虑writing a custom component并通过其渲染器发出标记。这可以与for属性一起使用,类似于label control。在同一NamingContainer中查找邻居相对容易。您可以在渲染器实现中使用这样的代码:

    // untested code!
    String clientId = mycomponent.getClientId(context);
    // get id of target control
    String _for = mycomponent.getFor();
    int n = clientId.lastIndexOf(NamingContainer.SEPARATOR_CHAR);
    String targetClientId = clientId.substring(0, n)
            + NamingContainer.SEPARATOR_CHAR + _for;
    ResponseWriter writer = context.getResponseWriter();
    // write markup
    

    组件通常需要共享一个命名容器,无论如何都要使用彼此的 clientId ,所以这不是一个很大的限制因素。如果您可以使组件成为子组件,则更容易找到父组件。

    当然,这种方法也存在问题。它使您的UI树更大,对生命周期处理和状态管理产生连锁反应。是否值得权衡需要进行测试。


    编辑:

    周末我想到了这个。由于50%的JSF查询似乎是关于如何使用ID的,所以我写了一篇文章,以便我可以引用人们 - JSF: working with component IDs。 In包含一个使用一些示例代码缓存ID (排序!)的机制。