2

この質問は、JSF2 への部分的な回答から生成されます: なぜコンポジットで panelGroup のレンダリングされた空のテストがアクションの呼び出しを妨げるのですか?

以下の Element は、名前と ID を持つ @Entity です。view.xhtml JSF ページは ID を viewParam として受け取り、 @ManagedBean @RequestScoped ElementController の setID(Long ID) を使用して、対応する Element のロードをデータベースからの ID でトリガーします (これは問題ではそれ以上の役割を果たしません)。 Element は、Element getSelected() として使用可能な「現在の」Element として設定されます (歴史的な理由により、名前が若干異なります)。

view.xhtml ページはレンダリングされた属性テスト #{not empty elementController.selected} を実行し、faces-redirect を実行するアクションを含む ah:commandButton をクエリ パラメータとしての id と共に、view.xhtml ページに戻します。

何らかの理由で完全には理解できませんが、フォームの送信時に、viewParam id が設定される前に (したがって、現在/選択された要素が設定される前に)、リクエストの適用フェーズとプロセスの検証フェーズの両方でテスト (および getSelected) が呼び出されます。モデル値の更新フェーズで検出および設定されます)。

大幅に省略された view.xhtml ページは次のとおりです。

<f:view>
 <f:metadata>
    <f:viewParam name="id" value="#{elementController.id}"/>
 </f:metadata>
</f:view>
<h:body>   
 <h:form>
   <h:panelGroup rendered="#{not empty elementController.selected}">
       <h:outputText value="#{elementController.selected.name}"/>
   </h:panelGroup>

   <h:commandButton value="Apply" action="#{elementController.action}" />

 </h:form>
</h:body>

(上記ではフォーム送信の意味が失われていますが、この質問には関係ありません。)

ElementController は RequestController を拡張します。

public void setId(Long id) {
log_debug("setId","id",id);
if (id != null) {
    this.id = id;
    T found = (T) getAbstractFacade().find(id);
    if (found == null) {
        String $error = "No object with id(" + id + ") found for class " + getManagedClass().getSimpleName();
        log_error($error);
    }
    setCurrent(found);
 }
}

public T getSelected() {
  log_debug("getSelected","current",current);        
  if (current == null) {
    log_warn("getSelected","null current Element");
   }
 return current;
}

public Object action() {
    String $i = "action";
    log_debug($i);
    if (current==null) {
        log_warn($i, "can't generate action outcome for null current element");
        return null;
    }
    return "/view?faces-redirect=true&id="+current.getId();
 }

フォーム送信時に getSelected() がたまたま 2 回呼び出され、current==null の場合は、リクエスト値の適用フェーズで 1 回、プロセス検証フェーズで 1 回です。 view.xhtml の viewParam のおかげで、id の設定 (および Element エンティティの読み込み) を行うことができます。

問題は、なぜ render=#{not empty elementController.selected} がリクエストの適用フェーズとプロセスの検証フェーズで呼び出されるのかということです。

これらのフェーズでは、id パラメータを指定して view.xhtml の初期 GET ロードを実行するときに呼び出されません。フォーム送信 POST とその後のリダイレクトおよび GET の間のみです。

4

1 に答える 1

4

ポストバック後にrendered属性が 2 回以上参照されるのは、JSF が各フェーズでコンポーネント ツリーをトラバースするためです。

「rendered」という名前は、適用されるコンポーネントのレンダリングを条件付きにするだけでなく、実際に一般的に処理するため、おそらく最適な名前ではありません。

コンポーネントとその子を処理して、それらのリクエスト値を適用する必要があるかどうかを確認するために、「リクエスト値の適用」について最初に参照されます。その値はフェーズ間で変更されている可能性があるため、「プロセスの検証」で再度参照されます。

「最初の GET ロードを実行するフェーズでは呼び出されません」。これは、GET を実行するときにコンポーネント ツリーがそれらのフェーズでトラバースされないためです (メタデータのみが処理されるため、ビュー パラメーターが特別な場所に置かれます)。メタデータ セクション)。

idGET リクエストから受け取った をポストバック後にアクション メソッドで使用できるようにするには、バッキング Bean にビュー スコープ ( ) を使用することをお勧めし@ViewScopedます。

于 2012-04-01T12:20:17.640 に答える