我想通过我提供的id从托管bean中找到一些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”?
答案 0 :(得分:41)
您可以使用以下代码:
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];
}
此代码将仅找到您通过id
的树中的第一个组件。如果树中有2个具有相同名称的组件,则必须执行自定义操作(如果它们位于2个不同的命名容器下,则可以这样做。)
答案 1 :(得分:2)
我尝试使用此代码,并提供帮助:
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;
}
由于
答案 2 :(得分:1)
也许这是不可能的。 FacesContext.getCurrentInstance().getViewRoot().findComponent(id)
方法只返回一个UIComponent
。 ViewRoot构造为树,因此如果视图中有两个表单,每个表单都带有id="text"
的组件,则它们会将其父组件添加到id中,这样它们就不会发生冲突。如果您将两个id="text"
组件放在同一表单中,则会抛出java.lang.IllegalStateException
。
如果要查找具有搜索到的id的所有组件,可以编写一个实现的方法:
List<UIComponent> foundComponents = new ArrayList();
for(UIComponent component: FacesContext.getCurrentInstance().getViewRoot().getChildren()) {
if(component.getId().contains("activityDescription")){
foundComponents.add(component);
}
}
或者如果您想找到第一个匹配项:
UIComponent foundComponent;
for(UIComponent component: FacesContext.getCurrentInstance().getViewRoot().getChildren()) {
if(component.getId().contains("activityDescription")){
foundComponent = component;
break;
}
}
答案 3 :(得分:1)
只需将prependId="false"
放入此textarea所在的表单中。
答案 4 :(得分:0)
是的,在NamingContainers
的所有父组件中,您必须添加属性prependId="false"
- 它肯定会在<h:form>
中运行,并且应该在其他组件中有效。
如果无法通过.xhtml文件中的属性进行设置,则必须设置此值为programaticaly。
提出问题的作者评论之后的建议:
如果您使用的组件中没有此类属性,请尝试使用以下方法编写查找方法:
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());
那会有帮助吗?