次のjsfを考えてみましょう:
<h:panelGroup id="current" rendered="#{taskManager.currentTask != null}">
<table>
<tr>
<td><h:outputText value="#{taskManager.currentTask.title}" /></td>
<td>
<h:form>
<rich:calendar id="start"
popup="true"
datePattern="yyyy-MM-dd HH:mm:ss"
showApplyButton="true" cellWidth="24px"
cellHeight="22px" style="width:200px"
enableManualInput="true"
value="#{taskManager.currentStart}">
</rich:calendar>
<h:commandButton value="Update">
<f:ajax execute="@form" render=":current" listener="#{taskManager.changeStart}"/>
</h:commandButton>
<h:commandButton value="Stop">
<f:ajax render=":current" listener="#{taskManager.stopCurrent}"/>
</h:commandButton>
</h:form>
</td>
</tr>
<tr>
<td></td>
<td>
<h:form>
<rich:calendar id="stop"
popup="true"
datePattern="yyyy-MM-dd HH:mm:ss"
showApplyButton="true" cellWidth="24px"
cellHeight="22px" style="width:200px"
enableManualInput="true"
value="#{taskManager.currentStop}">
</rich:calendar>
<h:commandButton value="Stop At">
<f:ajax execute="@form" render=":current" listener="#{taskManager.stopCurrentAtSpecified}"/>
</h:commandButton>
</h:form>
</td>
</tr>
</table>
</h:panelGroup>
ドキュメントから収集したように、部分ビュー「:current」が再レンダリングされる前に、f:ajax タグの「リスナー」を実行する必要があります。これは以下に基づいています。
- docs.oracle.com/javaee/6/tutorial/doc/gkace.html : リスナーの processAjaxBehavior メソッドは、ライフサイクルの Invoke Application フェーズで 1 回呼び出されます。
- javaserverfaces.java.net/nonav/docs/2.0/pdldocs/facelets/ : リクエスト処理ライフサイクルの「レンダリング」部分に参加するコンポーネントの識別子
- www.ibm.com/developerworks/library/j-jsf2/ : render は確かに呼び出し後です...
メソッド「#{taskManager.stopCurrentAtSpecified}」は、指定された時間にタスクを停止し、「null」に設定します。これは、再レンダリング時に評価「#{taskManager.currentTask != null}」が true でなくなることを意味し、グリッドパネルが消えるはずです。これはそうではありません。タスクは確かに停止していますが、再レンダリングされたビューにはまだ古いタスクが表示されています。ページ全体を更新すると、正しく表示されます。
さらに、「#{taskManager.changeStart}」をいじってみました。「#{taskManager.currentStop}」が非常に大きな日付に更新されるため、リスナーが実行されてからレンダリングが実行されたかどうか、カレンダーがこの大きな日付を反映するはずですが、そうではありません。
同様の問題を抱えている人を見つけましたが、彼の質問は未回答のままでした: f:ajax with listener and render
Mojarra 2.1.2 を使用しています