请看下面的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>
据我从文档中了解到,f:ajax标签中的“listener”应该在局部视图“:current”重新渲染之前被执行。这是基于以下内容:
- docs.oracle.com/javaee/6/tutorial/doc/gkace.html:在生命周期的调用应用程序阶段,将调用侦听器的processAjaxBehavior方法一次。
- javaserverfaces.java.net/nonav/docs/2.0/pdldocs/facelets/:在请求处理生命周期的“呈现”部分中将参与组件的标识符。
- www.ibm.com/developerworks/library/j-jsf2/:确实在调用后进行呈现......
方法“#{taskManager.stopCurrentAtSpecified}”将在给定时间停止任务并将其设置为“null”,这意味着在重新渲染时评估“#{taskManager.currentTask != null}”不再为真,因此网格面板应该消失。但事实并非如此。任务确实已停止,但重新渲染的视图仍显示旧任务。刷新整个页面将正确地呈现它。
另外,我尝试使用“#{taskManager.changeStart}”,将“#{taskManager.currentStop}”更新为一个非常大的日期,所以你会认为如果在执行侦听器和进行呈现后,日历将反映这个大日期,但实际上并不是这样。
我发现有人遇到了类似的问题,但他的问题没有得到解答:f:ajax with listener and render
我正在使用Mojarra 2.1.2