实际上在我的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可以使工作变得更快/更容易吗?
答案 0 :(得分:1)
不是我知道的。
很难缓存此信息,因为:
在尝试其他方法之前,我会证明这是一个问题。
你没有说明你需要什么 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 (排序!)的机制。