在JSF中按类型查找组件

Tar*_*rik 7 jsf uicomponents jsf-2

我的问题与这个问题有关.在JSF中动态获取所有隐藏的输入字段,但它与我想要使用JSF而不是纯HTML的不一样,并假设我的.xhtml文件中包含以下内容:

<h:inputHidden id="name1" value="SomeValue1"/>
<h:inputHidden id="name2" value="SomeValue2"/>
Run Code Online (Sandbox Code Playgroud)

我开发了一个小代码,我试图h:inputHidden动态获取所有标签并将其值打印到控制台,但问题是我无法找到一种方法如何使每一个动态.在我的代码中,id如果我想迭代uicomponents,我应该知道表单,如何迭代UIComponent组件树中的所有内容?(我试过,UIViewRoot#getChildren()但我只得到第一个孩子).

这是代码片段:

// 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());

}
Run Code Online (Sandbox Code Playgroud)

Bal*_*usC 11

你还需要迭代孩子的孩子,他们的孩子,等等.你看,它是一个组件.

这是一个实用程序方法的启动片段,它使用尾递归完全相同:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是您可以使用它的方法:

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());
}
Run Code Online (Sandbox Code Playgroud)

或者,更好,使用UIComponent#visitTree()它使用访问者模式.主要区别在于它还迭代迭代组件,例如<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);
}
Run Code Online (Sandbox Code Playgroud)

也可以看看:

毕竟,如果有必要,可以通过常规方式将它们绑定到bean属性最简单<ui:repeat>:

<h:inputHidden id="name1" value="#{bean.name1}"/>
<h:inputHidden id="name2" value="#{bean.name2}"/>
Run Code Online (Sandbox Code Playgroud)