4

「userId」と「name」という 2 つの変数があります。たとえば、「SHOW USERID」ボタンをクリックすると、正常に機能し、「renderUserId = true」が設定され、「render」で表示されますが、他の「SHOW」ボタンをクリックすると、Bean が再構築され、失われます「renderUserId=true」と「false」と「renderName=true」になるので、OKと表示されますが、USERIDは隠されています。

私の質問は、xhtml をレンダリングするときに Bean の値が失われないようにするにはどうすればよいですか?

これは私のコードの簡単なシミュレーションです。

注:「h:commandButton」で「f:setPropertyActionListener」の代わりに「actionListener」を使用すると、同じ結果が得られ、Bean が再構築されます。

example.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:a4j="http://richfaces.org/a4j"
    xmlns:cc="http://java.sun.com/jsf/composite">

    <cc:interface componentType="com.bean.ExampleBean">
        <cc:attribute name="userId" type="java.lang.Integer"/>
        <cc:attribute name="name" type="java.lang.String"/>
    </cc:interface>

    <cc:implementation>

        <h:panelGrid id="example_panel" columns="1" width="100%">

            <h:outputText value="USERID: #{cc.attrs.userId}" rendered="#{!cc.attrs.renderUserId}"/>

            <a4j:commandButton value="SHOW USERID" render="example_panel"
                rendered="#{!cc.attrs.renderUserId}">
                <f:setPropertyActionListener value="#{true}"
                    target="#{cc.attrs.renderUserId}"/>
            </a4j:commandButton>                
            <a4j:commandButton value="HIDE USERID" render="example_panel"
                rendered="#{cc.attrs.renderUserId}">
                <f:setPropertyActionListener value="#{false}"
                    target="#{cc.attrs.renderUserId}"/>
            </a4j:commandButton>                


            <h:outputText value="NAME: #{cc.attrs.name}" rendered="#{!cc.attrs.renderName}"/>

            <a4j:commandButton value="SHOW NAME" render="example_panel"
                rendered="#{!cc.attrs.renderName}">
                <f:setPropertyActionListener value="#{false}"
                    target="#{cc.attrs.renderName}"/>
            </a4j:commandButton>                
            <a4j:commandButton value="HIDE NAME" render="example_panel"
                rendered="#{cc.attrs.renderName}">
                <f:setPropertyActionListener value="#{false}"
                    target="#{cc.attrs.renderName}"/>
            </a4j:commandButton>                


        </h:panelGrid>

    </cc:implementation>

</ui:composition>

ExampleBean.java

import javax.faces.component.FacesComponent;
import javax.faces.component.UINamingContainer;


@FacesComponent("com.bean.ExampleBean")
public class ExampleBean extends UINamingContainer {

    private Integer userId;
    private String name;

    private boolean renderUserId;
    private boolean renderName;

}
4

2 に答える 2

12

ここには大きな誤解があります。それはバッキングビーンではありません。それがバッキングコンポーネントです。

JSF UI コンポーネント インスタンスはビュー スコープではなく、リクエスト スコープです。それらはレンダリング レスポンスの終了時に (状態を JSF ビュー ステートに保存した後) 破棄され、ビューのビルド時に再作成されます (状態は JSF ビュー ステートから復元されます)。

ステートフル プロパティをコンポーネントのインスタンス変数として割り当てました。これは正しくないです。それらを明示的に JSF 状態に格納する必要があります。そのための正しいアプローチは、ゲッターとセッターを に委譲させることUIComponent#getStateHelper()です。<cc:attribute>すでに暗黙的に宣言されている属性はすべて、それを行います。それらをバッキング コンポーネントのインスタンス変数として再宣言する必要はまったくありません。

として宣言されていないブール値は、<cc:attribute>次のように再実装する必要があります。

public Boolean getRenderUserId() {
    return (Boolean) getStateHelper().eval("renderUserId", Boolean.FALSE);
}

public void setRenderUserId(Boolean renderUserId) {
    getStateHelper().put("renderUserId", renderUserId);
}

アクション(リスナー)メソッドでは、setRenderUserId(true)それに応じて呼び出すだけです。

それに応じて EL 式を修正することを忘れないでください。

#{cc.renderUserId} 

以下も参照してください。

于 2013-04-10T13:07:08.887 に答える
1

FacesComponent は状態を保持しません。呼び出すたびに新しいインスタンスになります。あなたのユースケースでは、少なくともビュースコープで ManagedBean を使用する必要があるようです。これは、ボタンのあるページにいる限り、インスタンスが保持されることを意味します。

于 2013-04-10T11:09:17.440 に答える