在 JSF 中按类型查找组件
Posted
技术标签:
【中文标题】在 JSF 中按类型查找组件【英文标题】:Find component by type in JSF 【发布时间】:2015-04-18 11:52:19 【问题描述】:我的问题与Get all hidden input fields in JSF dynamically 相关,但这与我想使用 JSF 而不是纯 html 不同,并假设我的 .xhtml
文件中有以下内容:
<h:inputHidden id="name1" value="SomeValue1"/>
<h:inputHidden id="name2" value="SomeValue2"/>
我开发了一个小代码,尝试动态获取所有h:inputHidden
标签并将它们的值打印到控制台,但问题是我无法弄清楚如何让所有东西都动态化。在我的代码中,如果我想迭代 uicomponents,我应该知道 id
的形式,如何迭代组件树中的所有 UIComponent
? (我试过UIViewRoot#getChildren()
,但我只得到了第一个孩子)。
这里是sn-p的代码:
// formId is the id of my form
List<UIComponent> components = FacesContext.getCurrentInstance().getViewRoot().findComponent("formId").getChildren();
// A List of UIComponent where I am adding my Hidden Inputs
List<UIComponent> hiddenComponents = new ArrayList<UIComponent>();
for (UIComponent component : components)
// using the hidden inputs type in JSF: HtmlInputHidden
if (component instanceof HtmlInputHidden)
hiddenComponents.add(component);
for (UIComponent component : hiddenComponents)
// Printing the hidden inputs values for demonstration purposes
System.out.println(((HtmlInputHidden)component).getValue());
【问题讨论】:
【参考方案1】:您还需要迭代孩子的孩子,以及他们的孩子,等等。你看,它是一个组件tree。
这是一个实用方法的启动 sn-p,它使用 tail recursion 完成此操作:
public static <C extends UIComponent> void findChildrenByType(UIComponent parent, List<C> found, Class<C> type)
for (UIComponent child : parent.getChildren())
if (type.isAssignableFrom(child.getClass()))
found.add(type.cast(child));
findChildrenByType(child, found, type);
你可以这样使用它:
UIForm form = (UIForm) FacesContext.getCurrentInstance().getViewRoot().findComponent("formId");
List<HtmlInputHidden> hiddenComponents = new ArrayList<>();
findChildrenByType(form, hiddenComponents, HtmlInputHidden.class);
for (HtmlInputHidden hidden : hiddenComponents)
System.out.println(hidden.getValue());
或者,更好的是,使用UIComponent#visitTree()
,它使用visitor pattern。主要区别在于它还迭代了 <ui:repeat>
和 <h:dataTable>
等迭代组件,并为每次迭代恢复子状态。否则,当您将 <h:inputHidden>
包含在此类组件中时,您最终将得不到任何价值。
FacesContext context = FacesContext.getCurrentInstance();
List<Object> hiddenComponentValues = new ArrayList<>();
context.getViewRoot().findComponent("formId").visitTree(VisitContext.createVisitContext(context), new VisitCallback()
@Override
public VisitResult visit(VisitContext visitContext, UIComponent component)
if (component instanceof HtmlInputHidden)
hiddenComponentValues.add(((HtmlInputHidden) component).getValue());
return VisitResult.COMPLETE;
else
return VisitResult.ACCEPT;
);
for (Object hiddenComponentValue : hiddenComponentValues)
System.out.println(hiddenComponentValue);
另见:
How to collect values of an UIInput component inside an UIData component in bean's action method? How do I attach a FacesMessage from the backing bean to a specific field in a ui:repeat? Accessing dynamic UIComponents in JSF Managed Bean JSF 2 -- Save All Valid Component Values毕竟,最简单的方法是按照通常的方式将它们绑定到 bean 属性,如果需要的话,在 <ui:repeat>
中:
<h:inputHidden id="name1" value="#bean.name1"/>
<h:inputHidden id="name2" value="#bean.name2"/>
【讨论】:
所以我可以直接调用 UIViewRoot 上的findComponentsByType()
方法吗?万一我不知道表格ID?例如:findComponentsByType(context.getViewRoot(), hiddenComponents, HtmlInputHidden.class);
这是正确的吗?我们也可以对visitTree
做同样的事情吗?
你可以这样做。无论如何,它也是UIComponent
。请注意,我稍微重命名了方法/参数名称以提高自记录性。
是的,我刚刚注意到,最后一个问题,很抱歉打扰您:UIComponent#visitTree() 我们也可以直接在context.getViewRoot()
上调用它吗?
UIViewRoot
是一个UIComponent
。
我想你忘了修改findChildrenByType
函数中的findComponentsByType
名称。以上是关于在 JSF 中按类型查找组件的主要内容,如果未能解决你的问题,请参考以下文章
在 PrimeFaces 3.4 JSF 2.0 中按 id 查找组件
Ebean - 在 UUID 列类型中按 UUID 的一部分查找