考虑以下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 标记中的“监听器”应该在部分视图“:current”被重新渲染之前执行。这是基于:
- docs.oracle.com/javaee/6/tutorial/doc/gkace.html :在生命周期的 Invoke Application 阶段调用一次监听器的 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