Find component by type in JSF

前端 未结 1 1141
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-31 18:39

My question is related to this one Get all hidden input fields in JSF dynamically but it\'s not the same as I want to work with JSF and not plain HTML, and assuming that I h

相关标签:
1条回答
  • 2020-12-31 19:03

    You also need to iterate over children of children, and their children, etcetera. You see, it's a component tree.

    Here's a kickoff snippet of an utility method which does exactly that using 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);
        }
    }
    

    Here's how you could use it:

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

    Or, better, use UIComponent#visitTree() which uses the visitor pattern. The major difference is that it also iterates over iterating components such as <ui:repeat> and <h:dataTable> and restores the child state for every iteration. Otherwise you would end up getting no value when you have an <h:inputHidden> enclosed in such component.

    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);
    }
    

    See also:

    • 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

    After all, it's probably easiest to just bind them to a bean property the usual way, if necessary inside an <ui:repeat>:

    <h:inputHidden id="name1" value="#{bean.name1}"/>
    <h:inputHidden id="name2" value="#{bean.name2}"/>
    
    0 讨论(0)
提交回复
热议问题