-1

リストを反復処理するデータテーブルがあります。それを myList と呼びましょう。いくつかのリクエスト パラメータに基づいて、この myList にデータを入力します。データテーブル内には commandLinks があります。要求値の適用段階で myList にダミーのエントリを入れると、最初の commandLink をクリックすると、正常に機能します (アプリケーションの呼び出し段階で実行され、それまでに正しいエントリが myList に含まれます)。そうしないと、または 2 つ目以降の commandLink をクリックしても、何も起こりません。したがって、コマンドボタンの clientId は、アプリケーションの呼び出しフェーズでのみ使用されるとはいえ、リクエストの適用フェーズで解決され、commandLinks が壊れていると推測しています。

このようなもの:

<h:selectManyCheckbox styleClass="hidden" 
                      value="#{cc.attrs.selectionList.selected}"
                      converter="#{cc.attrs.converter}" >
    <f:selectItems value="#{cc.attrs.selectionList.all}"
                   var="item" itemValue="#{item}" itemLabel="" />
</h:selectManyCheckbox>
<h:dataTable value="#{cc.attrs.selectionList.selectedTest}" var="item">
    <h:column>
        <h:commandLink value="deselect" action="#{cc.attrs.selectionList.deSelect(item)}">
            <f:ajax execute=":#{component.parent.parent.parent.clientId}"
                    render=":#{component.parent.parent.parent.clientId}" />
        </h:commandLink>
    </h:column>
</h:dataTable>

そしてモデル:

public List<E> getSelected()
{
    return myList;
}

public List<E> getSelectedTest()
{
    if(FacesContext.getCurrentInstance().getCurrentPhaseId().equals(PhaseId.RESTORE_VIEW) && getSelectedList().isEmpty())
    {
        return Collections.singletonList(myList.get(0));
    }
    else if(FacesContext.getCurrentInstance().getCurrentPhaseId().equals(PhaseId.APPLY_REQUEST_VALUES) && getSelectedList().isEmpty())
    {
        return Collections.nCopies(2, myList.get(0));
    }
    else if(FacesContext.getCurrentInstance().getCurrentPhaseId().equals(PhaseId.PROCESS_VALIDATIONS) && getSelectedList().isEmpty())
    {
        return Collections.nCopies(3, myList.get(0));
    }
    else if(FacesContext.getCurrentInstance().getCurrentPhaseId().equals(PhaseId.UPDATE_MODEL_VALUES) && getSelectedList().isEmpty())
    {
        return Collections.nCopies(4, myList.get(0));
    }

    return myList;
}

public void deSelect(E item)
{
    myList.remove(item);
}

この例では、データテーブルの上位 2 つの commandLinks が機能します。私の質問は、なぜこの動作なのかということです.myListをダミーエントリで埋めずに回避する方法はありますか? データを保存するために (viewscoped) バッキング Bean を使用したくありません。

4

2 に答える 2

0

selectManyCheckbox 自体を componentBindings HashMap にバインドし、それを dataTable に使用する (selectManyCheckbox で immediate="true" を使用) ことで、どうにか回避することができました。

<h:selectManyCheckbox immediate="true" styleClass="hidden" 
                      binding="#{componentBindings[cc.attrs.selectionList]}"
                      value="#{cc.attrs.selectionList.selected}"
                      converter="#{cc.attrs.converter}" >
    <f:selectItems value="#{cc.attrs.selectionList.all}" var="item"
                   itemValue="#{item}" itemLabel="" />
</h:selectManyCheckbox>

<h:dataTable value="#{componentBindings[cc.attrs.selectionList].value}" var="item">
    <h:column>
        <h:commandLink value="deselect" action="#{cc.attrs.selectionList.deSelect(item)}">
            <f:ajax execute=":#{component.parent.parent.parent.clientId}"
                    render=":#{component.parent.parent.parent.clientId}" />
        </h:commandLink>
    </h:column>
</h:dataTable>

faces-config.xml で:

<managed-bean>
    <description>Holder of all component bindings.</description>
    <managed-bean-name>componentBindings</managed-bean-name>
    <managed-bean-class>java.util.HashMap</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
</managed-bean>
于 2013-01-20T07:20:28.563 に答える
0

リクエスト値の適用フェーズでは、クリックされたコマンド リンクを見つけるために、JSF はモデルを反復処理する必要があります。コマンド リンクを含むテーブルが表示される最初の HTTP 要求と比較して、フォーム送信が処理される HTTP 要求 (ポストバック) 中にモデルが非互換に変更された場合、JSF はクリックされたコマンド リンクを見つけることができないため、または、「現在の行」を表すオブジェクトがエンドユーザーが意図したものと同じではありません。

selectedTestBean がリクエスト スコープの場合、コンストラクタまたは@PostConstructメソッドでいくつかのリクエスト パラメータに基づいて初期化するように記述する必要があります。少なくとも、getters でビジネス ロジックを実行するべきではありません

selectedTestasを再構築するために必要なパラメーターを<f:param>コマンド リンクで渡すことができます。

<h:commandLink ...>
    <f:param name="some" value="#{bean.some}" />
</h:commandLink>

そして、次のようにモデルを準備します。

@ManagedProperty
private String some;

@PostConstruct
public void init(){ 
    selectedTest = populateItBasedOn(some);
}

// Don't change standard getters/setters!

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

于 2013-01-20T01:32:22.463 に答える