6

私のJSF2ベースのアプリケーションには、(他のUIコンポーネントの中でも)いくつかのチェックボックスを含むフォームがあります。

チェックボックスに、チェックされたときに起動するajaxリクエストを登録しました。ajaxリクエストは、実際にはバッキングBeanの別のチェックボックスの値を更新するだけです。その結果、他のチェックボックスもオンになります(再レンダリングされると、レンダリング応答フェーズでバッキングBeanから更新された値を取得するため)。

これは、フォーム全体が送信され、検証エラーが発生するまで正常に機能します。その後、ajaxリクエストは引き続き機能し、バッキングBeanの値を変更しますが、更新されたチェックボックスを再レンダリングするフェーズでは、その値はバッキングBeanからではなく、ComponentStateHelperクラスから取得されたキャッシュ値から取得されます。

私が理解している限り、これはJSF 2の新機能に使用され、コンポーネントツリーへの部分的な変更のみを保存します。

私が理解していないのは、これは検証フェーズとどのように関連しているのかということです。StateHelper検証でエラーが見つかったときに、チェックボックスのクラスにキャッシュされた値があるのはなぜですか?

4

1 に答える 1

4

これは既知の問題であり、この回答で詳細に説明されています。<f:ajax render>一言で言えば、によってレンダリングされるが実行されない無効化されたコンポーネント<f:ajax execute>は、元の送信された値とともに無効化された状態のままであるため、問題が発生します。JSFが入力コンポーネントをレンダリングするとき、JSFは最初に送信された値がそうでないかどうかをチェックしてnullから表示します。そうでない場合は、モデル値を表示します。基本的に、レンダリングされるがajaxによって実行されない入力コンポーネントの送信された値をリセットする必要があります。

これを実現するために、基本的に次のことを行うanActionListenerを使用できます。

UIViewRoot viewRoot = context.getViewRoot();
PartialViewContext partialViewContext = facesContext.getPartialViewContext();
Set<EditableValueHolder> inputs = new HashSet<EditableValueHolder>();

// First find all to be rendered inputs and add them to the set.
findAndAddEditableValueHolders(partialViewContext.getRenderIds(), inputs);

// Then find all executed inputs and remove them from the set.
findAndRemoveEditableValueHolders(partialViewContext.getExecuteIds(), inputs);

// The set now contains inputs which are to be rendered, but which are not been executed. Reset them.
for (EditableValueHolder input : inputs) {
    input.resetValue();
}

これはJSFissue1060として報告されており完全で再利用可能なソリューションがOmniFacesライブラリに実装されていますResetInputAjaxActionListener(ソースコードはこちら、ショーケースデモはこちら)。

于 2012-05-23T15:58:32.687 に答える