web-dev-qa-db-ja.com

valueChangeListenerまたはf:ajaxリスナーを使用する場合

listenerの配置に関して、次の2つのコードの違いは何ですか?

<h:selectOneMenu ...>
    <f:selectItems ... />
    <f:ajax listener="#{bean.listener}" />
</h:selectOneMenu>

そして

<h:selectOneMenu ... valueChangeListener="#{bean.listener}">
    <f:selectItems ... />
</h:selectOneMenu>
83
Danijel

valueChangeListenerは、フォームが送信されたときにのみ呼び出されますおよび送信された値は初期値とは異なります。したがって、onlyHTML DOM changeイベントが発生したときは呼び出されません。 HTML DOM changeイベント中にフォームを送信する場合は、リスナー(!)なしで別の<f:ajax/>を入力コンポーネントに追加する必要があります。現在のコンポーネントのみを処理するフォーム送信が行われます(execute="@this"のように)。

<h:selectOneMenu value="#{bean.value}" valueChangeListener="#{bean.changeListener}">
    <f:selectItems ... />
    <f:ajax />
</h:selectOneMenu>

valueChangeListenerの代わりに<f:ajax listener>を使用する場合、デフォルトでは既にHTML DOM changeイベント中に実行されます。 UICommandコンポーネントとチェックボックスまたはラジオボタンを表す入力コンポーネント内では、デフォルトでHTML DOM clickイベント中にのみ実行されます。

<h:selectOneMenu value="#{bean.value}">
    <f:selectItems ... />
    <f:ajax listener="#{bean.ajaxListener}" />
</h:selectOneMenu>

別の大きな違いは、valueChangeListenerメソッドがPROCESS_VALIDATIONSフェーズの終了時に呼び出されることです。その時点では、送信された値はモデルでまだ更新されていません。したがって、入力コンポーネントのvalueにバインドされているBeanプロパティにアクセスするだけでは取得できません。 ValueChangeEvent#getNewValue()で取得する必要があります。古い値は、ValueChangeEvent#getOldValue()でも利用可能です。

public void changeListener(ValueChangeEvent event) {
    Object oldValue = event.getOldValue();
    Object newValue = event.getNewValue();
    // ...
}

<f:ajax listener>メソッドは、INVOKE_APPLICATIONフェーズ中に呼び出されます。その時点で、送信された値はすでにモデルで更新されています。入力コンポーネントのvalueにバインドされているBeanプロパティに直接アクセスするだけで取得できます。

private Object value; // +getter+setter.

public void ajaxListener(AjaxBehaviorEvent event) {
    System.out.println(value); // Look, (new) value is already set.
}

また、送信された値に基づいてanotherプロパティを更新する必要がある場合、valueChangeListenerを使用しているときに失敗します更新されたプロパティは、後続のUPDATE_MODEL_VALUESフェーズ中に送信された値でオーバーライドできます。古いJSF 1.xアプリケーション/チュートリアル/リソースで、valueChangeListenerimmediate="true"およびFacesContext#renderResponse()と組み合わせて使用​​され、そのような構成が使用されないのは、まさにそのためです。結局、valueChangeListenerを使用してビジネスアクションを実行することは、実際には常にハック/回避策でした。

要約:valueChangeListenerは、実際の値の変化自体を傍受する必要がある場合にのみ使用してください。つまり実際に興味があるのはboth古い値と新しい値です(例:それらを記録するため)。

public void changeListener(ValueChangeEvent event) {
    changeLogger.log(event.getOldValue(), event.getNewValue());
}

<f:ajax listener>は、新しく変更された値に対してビジネスアクションを実行する必要がある場合にのみ使用します。つまり実際に興味があるのは、新しい値にonlyだけです(たとえば、2番目のドロップダウンに入力するため).

public void ajaxListener(AjaxBehaviorEvent event) {
    selectItemsOfSecondDropdown = populateItBasedOn(selectedValueOfFirstDropdown);
}

実際にビジネスアクションの実行中に古い値にも興味がある場合は、valueChangeListenerにフォールバックしますが、INVOKE_APPLICATIONフェーズにキューを入れます。

public void changeListener(ValueChangeEvent event) {
    if (event.getPhaseId() != PhaseId.INVOKE_APPLICATION) {
        event.setPhaseId(PhaseId.INVOKE_APPLICATION);
        event.queue();
        return;
    }

    Object oldValue = event.getOldValue();
    Object newValue = event.getNewValue();
    System.out.println(newValue.equals(value)); // true
    // ...
}
177
BalusC

最初のフラグメント(ajaxリスナー属性):

Ajaxタグの「リスナー」属性は、クライアント側でajax関数が発生するたびにサーバー側で呼び出されるメソッドです。たとえば、この属性を使用して、ユーザーがキーを押すたびに呼び出すサーバー側関数を指定できます

しかし、2番目のフラグメント(valueChangeListener):

ValueChangeListenerは、入力の値が変更されたときではなく、フォームが送信されたときにのみ呼び出されます

*あなたはこれを見たいかもしれません 便利な答え

9
a.u.r