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>

ドキュメントから収集したように、部分ビュー「: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 を使用しています

4

1 に答える 1

1

常に表示されている別の panelGroup を追加して再レンダリングしてみてください。何かのようなもの

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

部分的な更新により、要素のコンテンツが指定された ID に置き換えられます。更新された要素自体がレンダリングされない場合、問題になる可能性があると思います。レンダリング段階でスキップされ、結果として更新が生成されないことが予想されます。

余分なスパンを避けたい場合は、ネストされた h:panelGroup の代わりに ui:fragment または ui:component を使用してください。

于 2011-12-21T12:26:00.203 に答える