在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.IllegalStateException
exception。
如果你想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是。