3

我在应用程序中使用 Webflow 2.3.2,并且在一个步骤中,用户可以从绑定模型对象的列表中添加/删除(修改后他们只需返回到当前步骤)。例如,我的对象可能如下所示:

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 polyfill 来支持旧浏览器。


边注

由于从列表中选择一个项目(为了删除它,显示它,等等)是一个非常常见的用例,我喜欢使用一个自定义列表类,它允许您将索引绑定到列表本身:

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 回答
0

您可以在提交中使用参数来发送索引:

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

接着:

<transition on="deleteItem"  bind="false" validate="false">
    <set name="flowScope.indexDeleted" value="requestParameters.indexDeleted" type="long"/>
    <evaluate expression="flowService.deleteItem(flowScope.myInfo, flowScope.indexDeleted)"  result="flowScope.myInfo"  />
</transition>

最后:

public MyInfo deleteAccount(MyInfo myInfo, int indexDeleted) {
    myInfo.getMyList().remove(indexDeleted);
    return myInfo;
}
于 2013-10-09T19:25:19.287 回答