2013-09-02 2 views
3

У меня есть страница JSF, в которой я повторяю список в пределах <h:dataTable>, чтобы отобразить некоторые строки, содержащие флажок, некоторый текст и текстовое поле.Доступ к динамическим UIComponents в управляемом компоненте JSF

Я должен проверить <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 генерирует идентификаторы гт: 1: флажок, п.м.: 2: флажком и т.д., но когда я пытаюсь открыть компонент пользовательского интерфейса в JSF страницы, я не могу сделать это.

Я что-то упустил?

ответ

3

FacesContext#getViewRoot() возвращает дерево компонентов JSF. Это точно такое же дерево, как представлено исходным кодом XHTML, после того как задумано прочь все taghandlers (JSTL, <ui:include> и т. Д.). Вы должны понимать, что есть только один<h:selectBooleanCheckbox id="checkbox"> там. Он доступен в UIViewRoot#findComponent() именно этим ID "form:rm:checkbox".

Это просто его представление HTML, которое восстанавливается несколько раз в зависимости от текущего раунда итерации родителя <h:dataTable>. Это сгенерированное представление HTML имеет, в свою очередь, идентификаторы клиентов с текущим индексом строки inlined. Это представление HTML, очевидно, недоступно в дереве компонентов.

Состояние компонента (представленные значения и т. Д.) Также доступно только во время, итерации <h:dataTable> и не до или после. По сути, вы пытаетесь получить доступ к значению компонента в методе действия компонента, тогда как компонент <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().

+0

Спасибо за помощь. Мой новый вопрос можно найти в следующей ссылке: (http://stackoverflow.com/questions/18594896/switch-off-validations-during-ajax-call) –

Смежные вопросы