I have a strange problem with the <ui:repeat> . Even for my very simple example, value bindings inside nested repeat components do not work as expected.
I have a simple simple view:
<h:body> <h:form> <ui:repeat value="#{sandbox.rows}" var="row"> <ui:repeat value="#{row.columns}" var="column"> <h:outputText value="#{column.value}" /> <h:selectBooleanCheckbox value="#{column.value}" /> </ui:repeat> <br/> </ui:repeat> <h:commandButton action="#{sandbox.refresh}" value="Refresh" /> </h:form> </h:body>
and Sandbox class:
@Component @Scope("request") public class Sandbox { public static class Row { private List<Column> columns = Arrays.asList(new Column(), new Column()); public List<Column> getColumns() { return columns; } } public static class Column { private boolean value; public void setValue(boolean value) { this.value = value; } public boolean getValue() { return this.value; } } public List<Row> rows = Arrays.asList(new Row(), new Row()); public List<Row> getRows() { return rows; } public void refresh() { rows.get(0).getColumns().get(0).setValue(true); System.err.println("refresh clicked"); } }
So, my larva goes over the βrowsβ in the sandbox, in which there are several βcolumnsβ, each of which has a meaning. For each such column, a value is printed and <h:selectBooleanCheckbox> with the value associated with it.
When I load the page, all values ββare displayed as false and all checkboxes are not checked. Now click refresh should change the value of the first column of the first row to true. However, I get the following output:
true [] false []
false [] false []
In other words, <h:outputText> displays it as true, but the checkbox is not . Of course, I am allowed to change the model at the stage of the application-application, and what should be reflected in the visualization of the view?
If I remove one level of nesting, that is, only one <ui:repeat> , everything works as expected: the checkbox is checked and the value is displayed as true. So it looks like this is related to the UIRepeat component. In fact, it looks like UIRepeat has special handling when it is nested in another UIRepeat.
From what I am compiling, UIRepeat essentially repeats the same component several times. Between each visualization call, it loads a βstateβ (value, localValue, submittedValue) of all child components that implement the EditableValueHolder from the internal map (with the key to the actual component identifier). I tried to set breakpoints when this happens to keep track of which value is inserted into the saved state map, but this is really a mess, as the saveChildState and restoreChildState methods are called in about milliseconds.
Any ideas? Can I do otherwise? I really need to display a table dynamically growing both horizontally and vertically, containing checkboxes, input fields, etc. I took a look at <h:dataTable> , but I believe that this will not work in this case.