2011-11-28 38 views
3

我有,我想顯示問題的嵌套列表。最初,我正在顯示1級問題,然後根據用戶對其父問題的回答顯示子問題。所有的問題都有一個單選按鈕和一些問題,當有用戶選擇「是」阿賈克斯監聽事件valueChange似乎被解僱的onClick代替的onChange

這是我與嵌套數據表JSF代碼所顯示的附加信息的輸入框。請注意,我已經退出了對這些問題的格式,以簡單地在論壇上的問題,所以這些看起來「unpretty」如果您將此代碼複製到自己的環境和運行代碼:

<h:dataTable id="questionTable" var="q" value="#{generalQuestionBean2.questions.questions}"> 
<h:column><h:panelGroup id="questionGrp"> 
#{q.question} <h:selectOneRadio value="#{q.answer}"> 
<f:selectItem itemValue="1" itemLabel="Yes"/> 
<f:selectItem itemValue="0" itemLabel="No"/> 
<f:ajax event="valueChange" execute="@form" 
    render="questionGrp" 
    listener="#{generalQuestionBean2.reset}"/> 
</h:selectOneRadio> <h:inputText value="#{q.addnInfo}" 
rendered="#{q.answer eq '1' and q.field ne 'otherCov'}"></h:inputText> 

<h:panelGroup id="questionGrpSubs" rendered="#{q.addnQuestions ne null and q.answer eq '1'}"> 
<h:dataTable id="subQuestionTable" var="subq" value="#{q.addnQuestions}"> 
<h:column><h:panelGroup id="subQuestionGrp"> 
->#{subq.question} <h:selectOneRadio id="answer" value="#{subq.answer}"> 
<f:selectItem itemValue="1" itemLabel="Yes"/> 
<f:selectItem itemValue="0" itemLabel="No"/> 
<f:ajax event="valueChange" execute="@form" 
    render="subQuestionGrp" 
    listener="#{generalQuestionBean2.reset}"/> 
</h:selectOneRadio><h:inputText value="#{subq.addnInfo}" 
rendered="#{subq.answer eq '1' and subq.field ne 'voluntaryComp' and subq.field ne 'uslh'}"></h:inputText> 

<h:panelGroup id="questionGrpSubs2" rendered="#{subq.addnQuestions ne null and subq.answer eq '1'}"> 
<h:dataTable id="sub2QuestionTable" var="sub2q" value="#{subq.addnQuestions}"> 
<h:column><h:panelGroup id="sub2QuestionGrp"> 
-->#{sub2q.question} <h:selectOneRadio id="answer" value="#{sub2q.answer}"> 
<f:selectItem itemValue="1" itemLabel="Yes"/> 
<f:selectItem itemValue="0" itemLabel="No"/> 
<f:ajax event="valueChange" execute="@form" 
    render="sub2QuestionGrp" 
    listener="#{generalQuestionBean2.reset}"/> 
</h:selectOneRadio><h:inputText value="#{sub2q.addnInfo}" 
rendered="#{sub2q.answer eq '1'}"></h:inputText> 

</h:panelGroup></h:column> 
</h:dataTable></h:panelGroup> 
</h:panelGroup></h:column> 
</h:dataTable></h:panelGroup> 
</h:panelGroup></h:column> 
</h:dataTable> 

這裏是支持bean復位功能的代碼:

private void reset(AjaxBehaviorEvent event) { 
    FacesContext context = FacesContext.getCurrentInstance(); 
    String id = event.getComponent().getClientId(context); 
    String[] tokens = id.split("[:]+"); 
    int qId = -1; 
    int subqId = -1; 
    int sub2qId = -1; 
    for (int i = 0; i < tokens.length; i++) { 
     if(tokens[i].equals("questionTable")) 
      qId = Integer.parseInt(tokens[i+1]); 
     if(tokens[i].equals("subQuestionTable")) 
      subqId = Integer.parseInt(tokens[i+1]); 
     if(tokens[i].equals("sub2QuestionTable")) 
      sub2qId = Integer.parseInt(tokens[i+1]); 

    } 
    Question q = questions.getQuestion(qId); 
    Question processQ = q; 
    String defaultSubAnswer = getDefaultSubAnswer(q.getField()); 
    Question subq; 
    Question subq2; 
    if(subqId > -1) { 
     subq = q.getAddnQuestions().get(subqId); 
     processQ = subq; 
     if(sub2qId > -1) { 
      subq2 = subq.getAddnQuestions().get(sub2qId); 
      processQ = subq2; 
     } 
    } 
    resetValue(processQ, defaultSubAnswer); 
} 


private void resetValue(Question q, String defaultSubAnswer) { 
    q.setAddnInfo(""); 
    if(q.getAddnQuestions() != null) { 
     for (int i = 0; i < q.getAddnQuestions().size(); i++) { 
      Question subq = q.getAddnQuestions().get(i); 
      subq.setAnswer(defaultSubAnswer); 
      resetValue(subq, defaultSubAnswer); 
     } 
    } 
} 

現在的問題是:

阿賈克斯事件應該默認爲「valueChange」。如果我點擊「是」,然後再次點擊「是」,那麼ajax調用應該不會發生,對嗎?但它是,因爲附加信息框基於復位功能清除。

我最初嘗試給復位函數添加一個條件來檢查被點擊的按鈕的值,並且如果答案是「0」(否),只重置addnInfo值和子問題。但是這會導致渲染問題,因爲ajax調用會使輸入框和子問題隱藏起來,並且值將保留在前端,即使它們在後臺bean上重置。當他們重新渲染到前面時,保留的值顯示出來而不是後備bean中的值。

另一種嘗試是使用ValueChangeListener的值的復位。但是這仍然與重新渲染時保留的值有相同的問題。

我試圖3種不同的方法(上面列出),並都失敗了。我很樂意聽取任何這些或可能的解決方案的解決方案。請記住,用戶的格式限制使我用更少的選項來處理。

回答

4

阿賈克斯監聽事件valueChange似乎被解僱,而不是的onChange的onClick

這的確是它被用於通過由各自的JSF組件genreated單選按鈕和複選框默認valueChange事件。檢查生成的HTML源代碼,你會發現它被連接到onclick。 JSF爲什麼默認這樣做對於複選框是明確的,但乍看起來對於單選按鈕並不完全清楚,因爲無論如何它們都不會被取消。真正的原因在於它是爲了確保IE6/7兼容性而完成的,因爲onchange不會在該瀏覽器的第一次點擊中被解僱。

如果您不關心IE6/7用戶(其分佈最近發生嚴重下降),那麼將其更改爲event="change"

<f:ajax event="change" ... /> 

這樣JSF將生成onchange的事件處理程序。


更新:你可以使用jQuery.on('change')功能粘合劑將固定在change事件的IE6/7的不當行爲。

<script src="http://code.jquery.com/jquery-latest.min.js"></script> 

並執行此功能上載:

$(function() { 
    $(':radio').each(function() { 
     var handler = this.onclick; 
     this.onclick = null; 
     $(this).on('change', handler); 
    }); 
}); 

這將基本上每個無線按鈕移動JSF生成onclick屬性,如果你不是已經使用jQuery在<h:head>包括以下change由jQuery管理的事件處理程序,以便它可以在所有瀏覽器(包括IE6/7)中運行。

我們當然也可以用普通的JS來做,但是這需要很多樣板和跨瀏覽器的敏感代碼。

+0

不幸的是,我們需要IE兼容,所以上述解決方案將無法正常工作。我確實在Firefox上試過它,並且效果很好,但對於IE(我們很多用戶正在使用)而言,這並不可取。 –

+0

這將需要一些好的基於JavaScript的瀏覽器嗅探和黑客... – BalusC