3

考虑以下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

4

1 回答 1

1

您可以尝试添加另一个始终可见的 panelGroup 并重新渲染吗?就像是

<h:panelGroup id="current">
  <h:panelGroup rendered="#{taskManager.currentTask != null}">
    ...
  </h:panelGroup>
</h:panelGroup>

部分更新用指定的 id 替换元素的内容。我怀疑当更新的元素本身未呈现时可能会出现问题。我希望它在渲染阶段被跳过,因此不会生成更新。

如果您想避免额外的跨度,请使用 ui:fragment 或 ui:component 而不是嵌套的 h:panelGroup。

于 2011-12-21T12:26:00.203 回答