9

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

<h:inputHidden id="name1" value="SomeValue1"/>
<h:inputHidden id="name2" value="SomeValue2"/>

我开发了一个小代码,我试图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());

}
4

1 回答 1

14

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

这是一个实用方法的启动片段,它使用尾递归完全做到这一点:

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()使用访问者模式。主要区别在于它还对迭代组件进行迭代,例如<ui:repeat>and<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);
}

也可以看看:

毕竟,如果需要的话,以通常的方式将它们绑定到 bean 属性可能是最简单的<ui:repeat>

<h:inputHidden id="name1" value="#{bean.name1}"/>
<h:inputHidden id="name2" value="#{bean.name2}"/>
于 2015-02-17T17:55:10.740 回答