Jsf 计算UIComponent客户端ID的有效方法?
实际上,在我的JSF应用程序中,我有以下代码来根据组件id计算组件clientId:Jsf 计算UIComponent客户端ID的有效方法?,jsf,Jsf,实际上,在我的JSF应用程序中,我有以下代码来根据组件id计算组件clientId: public static String getComponentClientId(String id) { try { FacesContext fctx = FacesContext.getCurrentInstance(); UIComponent found = getComponentWithId(fctx.getViewRoot(), id); if (found!=nu
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;
}
公共静态字符串getComponentClientId(字符串id){
试一试{
FacesContext fctx=FacesContext.getCurrentInstance();
UIComponent found=getComponentWithId(fctx.getViewRoot(),id);
如果(找到!=null)
找到返回。getClientId(fctx);
其他的
返回null;
}捕获(例外e){
返回null;
}
}
公共静态UIComponent getComponentWithId(UIComponent父级,字符串id){
for(迭代器chs=parent.getFacetsAndChildren();chs.hasNext();){
UIComponent ch=chs.next();
if(ch.getId().equalsIgnoreCase(id))
返回ch;
否则{
UIComponent found=getComponentWithId(ch,id);
如果(找到!=null)
发现退货;
}
}
返回null;
}
该方法可以工作,但它可以在视图组件树中导航,因此效率可能非常低,特别是在存在高度填充的页面时。有一种我不知道的聪明方法或API可以使工作更快/更容易?我不知道
很难缓存此信息,因为:
你没有说你需要clientid做什么,但我猜它是为了某种形式的JavaScript支持。考虑并通过其渲染器发布标记。这可以与属性一起使用,类似于。在同一个房间里找到邻居相对容易。您可以在渲染器实现中使用如下代码:
// 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查询似乎都是关于如何使用IDs的,所以我写了一篇文章,这样我就可以让人们参考它了。在中包含了一种缓存ID的机制(有点!)和一些示例代码。据我所知不是这样 很难缓存此信息,因为:
你没有说你需要clientid做什么,但我猜它是为了某种形式的JavaScript支持。考虑并通过其渲染器发布标记。这可以与属性一起使用,类似于。在同一个房间里找到邻居相对容易。您可以在渲染器实现中使用如下代码:
// 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查询似乎都是关于如何使用IDs的,所以我写了一篇文章,这样我就可以让人们参考它了。中包含一种缓存ID的机制(有点!)和一些示例代码。谢谢你,McDowell。我只需要ClientID来发送正确组件的消息。我不想将每个组件都绑定到我的支持bean:这是一种正确的方法吗?看看taglib函数(参见博客链接)。如果你能改进我的解决方案,我很想听听。谢谢你,麦克道尔。我只需要ClientID来发送正确组件的消息。我不想将每个组件都绑定到我的支持bean:这是一种正确的方法吗?看看taglib函数(参见博客链接)。如果你能改进我的解决方案,我很想听听。仅供参考:只有在视图的ID是唯一的情况下,此算法才有效。最近回到规范,我注意到组件标识符只需要对最近的NamingContainer唯一。仅供参考:只有当ID对视图唯一时,该算法才有效。回到最近的规范,我注意到组件标识符只需要对最近的NamingContainer是唯一的。