3

JSF ページに渡されるさまざまなオプションのビュー パラメーターと、パラメーターが設定された後に処理される後続のビュー アクションを持つ設定があります。非常に簡単な例を以下に示します。

page.xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://xmlns.jcp.org/jsf/html"
  xmlns:f="http://xmlns.jcp.org/jsf/core">

<f:view>
    <f:metadata>
        <f:viewParam name="a" value="#{page.a}"/>
        <f:viewAction action="#{page.populateA()}" if="#{not empty page.a}"/>

        <f:viewParam name="b" value="#{page.b}"/>
        <f:viewAction action="#{page.populateB()}"/>
    </f:metadata>

    <h:outputLabel value="#{page.message}"/>
</f:view>
</html>

ページ

import javax.faces.view.ViewScoped;
import javax.inject.Named;

@ViewScoped
@Named
public class Page {

    private String a;

    private String b;

    private String message;

    public String getA() {
        return a;
    }

    public void setA(String a) {
        this.a = a;
    }

    public String getB() {
        return b;
    }

    public void setB(String b) {
        this.b = b;
    }

    public String getMessage() {
        return message;
    }

    public void populateA() {
        this.message = "Param a given: " + this.a;
    }

    public void populateB() {
        if (this.b != null) {
            this.message = "Param b given: " + this.b;
        }
    }
}

さて、違いは、の処理がa機能しないことです (page.xhtml?a=123) 一方で、の処理はb魅力のように機能します (page.xhtml?b=123) - 単にヌルを移動したと思っていても- JavaからJSFまで確認してください。読みやすさに関しては、Java での追加の null チェックを省略し、ビュー パラメータの処理を JSF に完全に配置することを好みますが、最初のシナリオを機能させるにはどうすればコードを微調整できますか?

編集f:viewAction のレンダリングされた属性の目的は何ですか?の受け入れられた回答によると、、ifそれ自体は機能するので、実行順序が間違っていると思われます(最初にアクション条件を評価してから、値をモデルに適用します)。

4

1 に答える 1

7

<f:viewAction if>属性は基本的に名前が変更された属性<h:xxx rendered>です (より明確かどうかは途中で残します。結果として、自動生成されたドキュメントに少なくともバグがrenderedあります。代わりにリストされますif) 。 Request Valuesフェーズを他のすべての UI コンポーネントとして適用します。このフェーズはUIComponent#decode()、ビュー内のすべての UI コンポーネントの を呼び出します。タグのUIViewAction背後にある UI コンポーネント クラスであるについては、次のように記述されます。<f:viewAction>decode()

次の条件のいずれかに該当する場合は、何もしません。

  • 現在のリクエストはポストバックであり、インスタンスはポストバックで動作しないように構成されています。を参照してくださいisOnPostback()

  • プロパティで指定された条件はiffalse と評価されます。見るisRendered()

そうです、あなたは「間違った実行順序」については確かに正しいです。Apply Request Valuesフェーズ中に属性をチェックし、if評価されfalseた場合、デコードは行われず、アクション イベントはキューに入れられません。UIViewAction ソース コードの644 行目も参照しisRendered()decode()くださいfalse。あなたの場合、 で#{page.a}チェックしている は、リクエスト値の適用フェーズの後にあるモデル値の更新フェーズで<f:viewAction if>のみ使用できます。

Apply Request Valuesフェーズで利用可能であることが保証されている他の何かをテストしたいと考えています。最良の候補は、実際のリクエスト パラメータそのものです。すべての「プレーンな」リクエスト パラメータは、パラメータ名をキーとして参照する暗黙的な EL オブジェクトによって使用可能な EL スコープ内にあります。 #{param}Map<String, String>

したがって、全体として、これは次のようにする必要があります。

<f:viewParam name="a" value="#{page.a}"/>
<f:viewAction action="#{page.populateA}" if="#{not empty param.a}"/>

の非直感的な動作を解決するための更新。バージョン 2.2 以降<f:viewAction if>、JSF ユーティリティ ライブラリOmniFacesは、アクション イベントがブロードキャストされる直前のInvoke Applicationフェーズでのみ評価される<o:viewAction>を提供します。このトリックは、コンポーネントを拡張し、そのandを次のようにオーバーライドするだけで実行できました。ifUIViewActionbroadcast()isRendered()

@Override
public void broadcast(FacesEvent event) throws AbortProcessingException {
    if (super.isRendered()) {
        super.broadcast(event);
    }
}

@Override
public boolean isRendered() {
    return !isImmediate() || super.isRendered();
}

これにより、タグをより直感的に使用できます。

<f:viewParam name="a" value="#{page.a}"/>
<o:viewAction action="#{page.populateA}" if="#{not empty page.a}"/>
于 2014-08-11T20:46:17.623 に答える