3

私はアプリケーションで Webflow 2.3.2 を使用しています。1 つのステップで、ユーザーはバインドされたモデル オブジェクトのリストに追加/削除できます (変更後に現在のステップに戻るだけです)。たとえば、私のオブジェクトは次のようになります。

public class MyInfo implements Serializable {
    List<String> myList = new ArrayList<String>();
}

リストの最後に新しいオブジェクトを貼り付けるだけなので、webflow で「追加」を行うことは問題ありませんが、「削除」の場合は、削除する要素を特定する必要があります。私が今行っているのは、事前定義された「currentEvent」EL オブジェクトを使用し、削除するレコードの ID を入力した生のイベント「値」を取得することです。これは長い道のりのように見えるので、これを行うためのよりエレガントな方法があるかどうか疑問に思っています。 誰でもこれを行うためのより良い方法を提案できますか? これが私が今やっていることの図です:

私のJSPファイル(「削除」ボタンに注意してください):

<c:forEach items="${myInfo.myList}" var="listItem" varStatus="listItemStatus">
    <c:set var="v" value="${listItemStatus.index}"/>
    <div><form:input id="listItemValue_${v}" path="myInfo.myList[${v}]"/></div>
    <div><button id="deleteItem_${v}" name="_eventId_deleteItem" type="submit" value="${v}">Delete This Item</button></div>
</c:forEach>

私の「flow.xml」ファイル:

<transition on="deleteItem"  bind="false" validate="false">
    <evaluate expression="flowService.deleteItem(flowScope.myInfo, currentEvent.attributes)"  result="flowScope.myInfo"  />
</transition>

私のイベントハンドラ:

public MyInfo deleteAccount(MyInfo myInfo, LocalAttributeMap currentEvent) {
    myInfo.getMyList().remove(Integer.valueOf((String)(currentEvent.asMap().get("_eventId_deleteItem"))).intValue());
    return myInfo;
}
4

2 に答える 2

5

主な問題は_eventId、単一の<button type='submit'/>要素を使用してアカウント インデックスとアカウント インデックスの両方を送信する方法です。

これはまさにこの問題に関する素晴らしい質問と回答です: HTMLフォームのネスト制限をどのように克服しますか? . いずれにせよ、送信ボタンはすべての非表示の入力を送信するため、アカウント インデックスで非表示の入力を使用しても役に立ちません。

もちろん、他に何も送信したくない場合は、送信ボタンの代わりにアンカーを使用できます。

<a href="${flowExecutionUrl}&_eventId=deleteItem&index=${v}">Delete This Item<a>

<transition on="deleteItem"  bind="false" validate="false">
    <evaluate expression="flowService.deleteItem(flowScope.myInfo, requestParameters.index)" result="flowScope.myInfo"/>
</transition>

ただし、意味的には、「削除」操作は HTTP GET 要求であってはなりません。とにかく、アンカーを使用する傾向があります。しかし、リンクされた質問を読んだ後、HTML5 の代替手段である "formaction" 属性があることがわかりました。この場合、JSP は次のようになります。

<form:form action="${flowExecutionUrl}" method="post" commandName="backingObject">

<c:forEach items="${myInfo.myList}" var="listItem" varStatus="status">

    <form:input path="myInfo.myList[${status.index}]"/>

    <button type="submit" name="index" value="${status.index}" 
           formaction="${flowExecutionUrl}&_eventId=deleteItem">
        Delete This Item
    </button>

</c:forEach>

</form:form>

基本的に、選択されたボタンは、囲んでいるフォームの「アクション」属性をオーバーライドして、_eventIdパラメーターを含めます。

ブラウザーのサポートを考慮する必要がありますが、古いブラウザーをサポートするために JavaScript ポリフィルを提供できる場合があります。


サイドノート

リストからアイテムを選択する (削除、表示などの目的で) ことは非常に一般的なユースケースであるため、インデックスをリスト自体にバインドできるカスタム リスト クラスを使用するのが好きです。

public class SelectionList<T> extends ArrayList<T> {

    // the index of the selected item within the list
    private Integer index;

    public SelectionList() {
    }

    public SelectionList(Collection<? extends T> c) {
        super(c);
    }

    // this is used for binding to/from the view layer, and shouldn't be called by application code
    public Integer getIndex() {
        return index;
    }

    // this is used for binding to/from the view layer, and shouldn't be called by application code
    public void setIndex(Integer index) {
        this.index = index;
    }

    // use this to retrieve the selected item from the list.
    public T getSelectedItem() {
        if (index == null || index >= super.size() || index < 0) {
            return null;
        }
        return super.get(index);
    }
}

次に、選択したインデックスをリストに直接バインドし、list.getSelectedItem()バインドが発生した後に呼び出すだけです。

于 2013-10-10T12:20:52.010 に答える