У меня странная проблема с тегом <ui:repeat>
.Даже для моего очень простого примера привязки значений внутри вложенных повторяющихся компонентов не работают должным образом.
У меня есть простой фасет, подобный так:
<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>
и класс Sandbox:
@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");
}
}
Таким образом, моя лицевая сторона зацикливается на «строках» в песочнице, в которой есть несколько «столбцов», каждый из которых имеет значение.Для каждого такого столбца выводится значение, и выводится <h:selectBooleanCheckbox>
со значением, связанным с ним.
Когда я загружаю страницу, все значения отображаются как ложные, а все флажки сняты.Теперь нажатие кнопки «Обновить» должно изменить значение первого столбца первой строки на true.Однако я получаю следующий вывод:
true [ ] false [ ]
false [ ] false [ ]
Другими словами, <h:outputText>
отображает его как true, но флажок не отмечен .Конечно, мне разрешено изменять модель на этапе вызова приложения, и это должно быть отражено при рендеринге представления?
Если я удаляю один уровень вложенности, то есть только один <ui:repeat>
, все работает как положено: флажок установлен, и значение отображается как true.Так что, похоже, это как-то связано с компонентом UIRepeat.На самом деле, кажется, что UIRepeat имеет некоторую специальную обработку, когда он вложен в другой UIRepeat.
Из того, что я понял, UIRepeat, по сути, переопределяет один и тот же компонент несколько раз.Между каждым вызовом рендеринга он загружает «состояние» (значение, localValue, submitValue) всех дочерних компонентов, реализующих EditableValueHolder
, из внутренней карты (на основе фактического идентификатора визуализированного компонента).Я пытался поставить точки останова, когда это происходит, чтобы отследить, какое значение вставлено в карту сохраненных состояний, но это действительно беспорядок, так как методы saveChildState и restoreChildState вызываются около миллиарда раз.
Любые идеи?Могу ли я пойти по этому поводу по-другому?Что мне действительно нужно, так это уметь отображать таблицу, которая динамически растет как по горизонтали, так и по вертикали, содержащую флажки, поля ввода и т. Д. Я взглянул на <h:dataTable>
, но я считаю, что в этом случае это не будет работать.