在JSF中通过ID查找组件

我想通过我提供的id从托pipebean中find一些UIComponent

我写了下面的代码:

 private UIComponent getUIComponent(String id) { return FacesContext.getCurrentInstance().getViewRoot().findComponent(id) ; } 

我已经定义了一个p:inputTextarea为:

 <p:inputTextarea id="activityDescription" value="#{adminController.activityDTO.activityDescription}" required="true" maxlength="120" autoResize="true" counter="counter" counterTemplate="{0} characters remaining." cols="80" rows="2" /> 

现在,如果调用方法getUIComponent("activityDescription")它返回null ,但如果我把它称为getUIComponent("adminTabView:activityForm:activityDescription")那么我可以得到org.primefaces.component.inputtextarea.InputTextarea实例。

有没有什么办法让组件只有ID即“activityDescription”不是绝对的ID即“adminTabView:activityForm:activityDescription”?

您可以使用下面的代码:

 public UIComponent findComponent(final String id) { FacesContext context = FacesContext.getCurrentInstance(); UIViewRoot root = context.getViewRoot(); final UIComponent[] found = new UIComponent[1]; root.visitTree(new FullVisitContext(context), new VisitCallback() { @Override public VisitResult visit(VisitContext context, UIComponent component) { if(component.getId().equals(id)){ found[0] = component; return VisitResult.COMPLETE; } return VisitResult.ACCEPT; } }); return found[0]; } 

这段代码只会find树中第一个带有你传递的id组件。 如果在树中有两个相同名称的组件(如果它们位于两个不同的命名容器中,则这是可能的),您将不得不执行一些自定义操作。

也许这是不可能的。 FacesContext.getCurrentInstance().getViewRoot().findComponent(id)方法只返回一个UIComponent 。 ViewRoot被构造为一棵树,所以如果你在视图中有两个表单,每个表单都带有一个id="text"的组件,那么它们将把它的父组件添加到这个id中,这样它们就不会发生冲突。 如果将两个id="text"组件放在同一个表单中,则会抛出java.lang.IllegalStateExceptionexception。

如果你想find所有与search的ID组件,你可以写一个方法,实现:

 List<UIComponent> foundComponents = new ArrayList(); for(UIComponent component: FacesContext.getCurrentInstance().getViewRoot().getChildren()) { if(component.getId().contains("activityDescription")){ foundComponents.add(component); } } 

或者如果你想find第一个发生:

 UIComponent foundComponent; for(UIComponent component: FacesContext.getCurrentInstance().getViewRoot().getChildren()) { if(component.getId().contains("activityDescription")){ foundComponent = component; break; } } 

我尝试这个代码,这是帮助:

 private static UIComponent getUIComponentOfId(UIComponent root, String id){ if(root.getId().equals(id)){ return root; } if(root.getChildCount() > 0){ for(UIComponent subUiComponent : root.getChildren()){ UIComponent returnComponent = getUIComponentOfId(subUiComponent, id); if(returnComponent != null){ return returnComponent; } } } return null; } 

谢谢

是的,在NamingContainers所有父组件中,您必须添加属性prependId="false" – 它肯定会在<h:form>中起作用,并且应该可以在其他组件中使用。
如果无法通过.xhtml文件中的属性进行设置,则必须设置这样的值程序。

问题作者评论后的build议:

如果你正在使用的组件中没有这样的属性,请尝试写这样的方法:

 private UIComponent findComponent(String id, UIComponent where) { if (where == null) { return null; } else if (where.getId().equals(id)) { return where; } else { List<UIComponent> childrenList = where.getChildren(); if (childrenList == null || childrenList.isEmpty()) { return null; } for (UIComponent child : childrenList) { UIComponent result = null; result = findComponent(id, child); if(result != null) { return result; } return null; } 

接下来只是调用

 UIComponent iamLookingFor = findComponent(myId, FacesContext.getCurrentInstance().getViewRoot()); 

这将有助于?

只需把prependId="false"放在你的表单里,这个textarea是。