Доступ к динамическим компонентам UIC в JSF Managed Bean
У меня есть страница JSF, в которой я перебираю список в <h:dataTable>
отобразить несколько строк, содержащих флажок, текст и текстовое поле.
Я должен подтвердить <h:dataTable>
так что когда пользователь проверяет флажок, он должен ввести некоторый текст внутри текстового поля.
Это моя страница JSF.
<h:form prependId="false" id="form">
<h:dataTable id="rm" width="100%" cellspacing="4"
value="#{controller.alertTriggers}" var="alt"
columnClasses="c1,c2,c3,c4">
<h:column>
<h:selectBooleanCheckbox value="#{alt.checkValue}" id="checkbox"/>
</h:column>
<h:column>
<h:outputText value="#{alt.id}" />
</h:column>
<h:column>
<h:outputFormat value="#{alt.msg1}" />
</h:column>
<h:column>
<h:message for="emailID" id="email" styleClass="validation-error"/>
<h:inputText value="#{alt.mailId}" id="emailID" style="width: 87%;" />
</h:column>
</h:dataTable>
</h:form>
Я дал идентификатор всех флажков как checkbox
и идентификатор всех текстовых полей как emailID
, Когда страница отрисована, при проверке источника страницы я обнаружил, что идентификаторы флажков - "rm:0:checkbox", "rm:1:checkbox"... и идентификаторы текстовых полей - "rm: 0: EMAILID", 'тт: 1: EMAILID'..
В контроллере я хочу получить доступ к этим динамическим текстовым полям и флажкам, для которых я использую следующий код:
FacesContext context = FacesContext. getCurrentInstance();
for (int i=0;i<9;i++){
UIInput u=(UIInput) FacesContext.getCurrentInstance().getViewRoot().findComponent( "form:rm:" +i+":checkbox" );
if ((Boolean) u.getValue()){
UIInput ui=(UIInput) FacesContext.getCurrentInstance().getViewRoot().findComponent( "form:rm:" +i+":emailID" );
//code
}
}
Но это дает java.lang.NullPointerException
Даже используя код:
UIInput u=(UIInput) FacesContext.getCurrentInstance().getViewRoot().
findComponent( "form:rm:0:checkbox" ); gives the same exception.
Но если я использую
UIInput u=(UIInput) FacesContext.getCurrentInstance().getViewRoot().
findComponent( "form:rm:checkbox" );
это не дает исключение нулевого указателя, но я не знаю, какое значение этого флажка дает.
Итак, в итоге,
JSF генерирует идентификаторы как rm:1:checkbox,rm:2:checkbox и т. Д., Но когда я пытаюсь получить доступ к этому компоненту пользовательского интерфейса на странице JSF, я не могу это сделать.
Я что-то пропустил?
1 ответ
FacesContext#getViewRoot()
возвращает дерево компонентов JSF. Это то же самое дерево, которое представлено исходным кодом XHTML после обдумывания всех обработчиков тегов (JSTL, <ui:include>
, так далее). Вы должны понимать, что есть только один <h:selectBooleanCheckbox id="checkbox">
там. Это доступно в UIViewRoot#findComponent()
именно по этому идентификатору "form:rm:checkbox"
,
Это просто его HTML-представление, которое генерируется несколько раз в зависимости от текущего цикла итерации родительского элемента. <h:dataTable>
, Это сгенерированное представление HTML в свою очередь имеет идентификаторы клиента с текущим индексом строки. Это HTML-представление, очевидно, недоступно в дереве компонентов.
Состояние компонента (представленные значения и т. Д.) Также доступно только во время итерации <h:dataTable>
а не до или после. По сути, вы пытаетесь получить доступ к значению компонента в методе действия bean-компонента, пока <h:dataTable>
компонент не перебирает его, поэтому значения всегда будут возвращаться null
,
Для того, чтобы программно моделировать <h:dataTable>
итерации, так что вы можете собрать нужные значения, вам нужно посетить <h:dataTable>
от UIComponent#visitTree()
и собирать информацию, представляющую интерес в VisitCallback
реализация.
UIData table = (UIData) viewRoot.findComponent("form:rm");
table.visitTree(VisitContext.createVisitContext(FacesContext.getCurrentInstance()), new VisitCallback() {
@Override
public VisitResult visit(VisitContext context, UIComponent target) {
if (target instanceof HtmlSelectBooleanCheckbox) {
HtmlSelectBooleanCheckbox checkbox = (HtmlSelectBooleanCheckbox) target;
System.out.println("id: " + checkbox.getId());
System.out.println("value: " + checkbox.getValue());
// Collect them in an arraylist orso.
}
return VisitResult.ACCEPT;
}
});
Однако вы идете в совершенно неверном направлении в отношении решения конкретной проблемы. Вы должны выполнять проверку в валидаторе, связанном с компонентом ввода, который вы хотите проверить, а не в методе действия. Вот как вы можете решить конкретное функциональное требование проверки поля ввода как required
только когда установлен флажок в той же строке:
<h:column>
<h:selectBooleanCheckbox binding="#{checkbox}" ... />
</h:column>
<h:column>
<h:inputText ... required="#{checkbox.value}" />
</h:column>
Это все. Дополнительным преимуществом является то, что валидаторы работают, пока <h:dataTable>
повторяется, так что вам не нужно все это visitTree()
код также.