我在应用程序中使用Webflow 2.3.2,用户可以在一步中添加/删除绑定模型对象中的列表(它们只是在修改后返回到当前步骤)。例如,我的对象可能如下所示:
public class MyInfo implements Serializable {
List<String> myList = new ArrayList<String>();
}
在webflow中执行“添加”没有问题,因为我只是将新对象粘贴在列表的末尾,但对于“删除”,我需要标识要删除的元素。我现在正在做的是使用“currentEvent”预定义的EL对象并获取原始事件“value”,我已使用要删除的记录的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;
}
答案 0 :(得分:5)
似乎主要问题是如何使用单个_eventId
元素提交<button type='submit'/>
和帐户索引?
这是一个很棒的问题&amp;关于这个问题的答案:How do you overcome the html form nesting limitation?。使用带有帐户索引的隐藏输入无济于事,因为提交按钮无论如何都会提交所有隐藏的输入。
当然,只要您不想提交任何其他内容,您就可以使用锚点而不是提交按钮,例如
<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替代方案 - 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>
基本上,所选按钮会覆盖封闭表单的“操作”属性,以包含_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()
。
答案 1 :(得分: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">
<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;
}