Find component by type in JSF

My question is related to dynamically embed all hidden input fields in JSF , but this is not the same as I want to work with JSF, and not with regular HTML, and assuming the following is in my .xhtml file:

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

I developed a little code in which I tried to get all the h:inputHidden dynamically and print their values ​​on the console, but the problem is that I cannot figure out how to make any dynamics. In my code, I need to know the id form, if I want to Iterate over uicomponents, how can I iterate over all UIComponent in the component tree? (I tried UIViewRoot#getChildren() , but I only have first children).

Here is the code snippet:

 // 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()); } 
+6
source share
1 answer

You also need to sort out the children of the children, their children, etc. You see that this is a component of a tree .

Here's a kickoff snippet of a utility method that does just that using a recursion tail :

 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 you can 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 main difference is that it also iterates over iterative components like <ui:repeat> and <h:dataTable> , and restores the child state for each iteration. Otherwise, you will not get any value if this component has <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); } 

See also:

In the end, the easiest way is to simply bind them to the bean property in the usual way, if necessary inside <ui:repeat> :

 <h:inputHidden id="name1" value="#{bean.name1}"/> <h:inputHidden id="name2" value="#{bean.name2}"/> 
+9
source

Source: https://habr.com/ru/post/982622/


All Articles