【问题标题】:Spring Webflow - deleting an item from a list?Spring Webflow - 从列表中删除项目?
【发布时间】:2013-10-17 06:52:55
【问题描述】:

我在应用程序中使用 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;
}

【问题讨论】:

    标签: spring spring-webflow spring-webflow-2


    【解决方案1】:

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

    <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;
    }
    

    【讨论】:

    • 问题是点击提交按钮会提交所有隐藏的输入,除非你有单独的
      元素用于迭代 标签。
    • 我明白了,我用应该解决这个问题的东西编辑了我的答案
    • @rptmat57 我无法解析 flowScope.indexDeleted() ?你能发布整个解决方案吗?对不起,我是 Spring Webflow 开发的新手
    • indexDeleted(没有())应该作为您请求的参数。我添加了 &lt;set name="flowScope.indexDeleted" value="requestParameters.indexDeleted" type="long"/&gt; 行以转换为 long
    【解决方案2】:

    似乎主要问题是如何使用单个 &lt;button type='submit'/&gt; 元素同时提交 _eventId 和帐户索引?

    这是一个关于这个问题的好问题和答案:How do you overcome the html form nesting limitation?。使用带有帐户索引的隐藏输入没有帮助,因为提交按钮无论如何都会提交所有隐藏输入。

    当然,您可以使用锚点代替提交按钮,只要您不想提交任何其他内容,例如

    &lt;a href="${flowExecutionUrl}&amp;_eventId=deleteItem&amp;index=${v}"&gt;Delete This Item&lt;a&gt;

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

    但从语义上讲,“删除”操作不应该是 HTTP GET 请求。无论如何,我倾向于使用锚点,因为它似乎是最不老套的选择。但是,在阅读了链接的问题后,我发现有一个 HTML5 替代方案 - the "formaction" attribute。在这种情况下,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>
    

    基本上,所选按钮会覆盖封闭表单的“action”属性,以包含_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()

    【讨论】:

    • 感谢您的精彩回复 - 我认为您的锚点解决方案是最好的方法,正如您所说的那样,它是“最少的 hacky”。​​
    猜你喜欢
    • 1970-01-01
    • 2022-12-20
    • 2016-05-08
    • 2011-03-18
    • 1970-01-01
    • 2020-12-07
    • 2010-11-29
    • 2016-08-17
    相关资源
    最近更新 更多