问题描述
除了Set
之外,是否还有类似AutoPopulatingList
的东西?我要显示的数据是使用Set
的关联.
Is there anything like AutoPopulatingList
but for Set
?The data that I want to show is an association that uses Set
.
public class Employer implements java.io.Serializable {
private Set<Employee> employees = new HashSet();
}
我尝试使用AutoPopulatingList
,但是在这种情况下,我必须在休眠状态下使用List
,这需要我使用Employee.employeeId
指定list-index
,并且每当稍后通过Employee
检索employees
时,列表根据Employee.employeeId
在元素(null
元素)之间会有空格.
I've tried using AutoPopulatingList
but in that case I have to use List
in hibernate which needs me to specify list-index
using Employee.employeeId
and whenever I retrieve the employees
through Employee
later the list would have spaces between element (null
elements) depending on the Employee.employeeId
.
我需要自动填充集合,因为我需要在创建Employer
时动态生成employees
.使用普通Set
时得到以下信息:org.springframework.beans.InvalidPropertyException: Invalid property 'employees[0]' of bean class [model.Employer]: Cannot get element with index 0 from Set of size 0, accessed using property path 'employees[0]'
I need to auto-populate the collection because I need to generate the employees
dynamically while creating the Employer
.I got the following when I use plain Set
:org.springframework.beans.InvalidPropertyException: Invalid property 'employees[0]' of bean class [model.Employer]: Cannot get element with index 0 from Set of size 0, accessed using property path 'employees[0]'
还有其他解决方法吗?
修改
我正在尝试实现动态表单
I'm trying to implement dynamic form
推荐答案
您不能在MVC中将Set
用作绑定目标,因为无法为其项目创建属性路径.
You can not use Set
as a binding target in MVC because it is not possible to create property path for its items.
构建动态表单时,应使用Map<Integer, YourType>
.我们已经实施了很多次(所以我知道它正在工作)是这样的:
You should use Map<Integer, YourType>
when building dynamic forms. What we have implemented many times (so I know it is working) is this:
- 一个简单的数字序列用作键,而与实际项目没有任何联系
- 键顺序始终在增加,但不需要连续(例如,如果用户删除第二个项目,您将得到
1, 3, 4, ...
结束) - 如果要添加其他项目,只需找到最高编号,然后添加以
maxIndex + 1
索引的表格(总是增加顺序) -
LinkedHashMap
的Map
实现必须实例,以便保留迭代顺序(如果需要自动填充Map
字段,则默认情况下,Spring正在创建此实现) -
Map
必须是某些父表单对象的一部分(即您不能将Map
作为顶部表单对象),以便Spring能够从属性getter推断出通用类型
- a simple number sequence is used as keys without any connection to the actual items
- the key sequence is always increasing but doesn't need to be continuous (e.g. in case user will delete the second item, you will end up with
1, 3, 4, ...
) - if you want to add another item, you just find the highest number and then add form indexed with
maxIndex + 1
(always increasing sequence) - the
Map
implementation MUST BE instance ofLinkedHashMap
so that the iteration order is preserved (Spring is creating this implementation by default if aMap
field needs to be autopopulated) - the
Map
must be part of some parent form object (i.e. you can not haveMap
as the top form object) so that Spring is able to infer the generic types from the property getter
有很多方法可以使用它.例如,我们有一个特殊的 template子表单,当我们需要动态添加另一个子表单时使用.这种方法可能要复杂一些:
There are many ways how you can work with this. For example we have a special template subform, which is used when we need to dynamically add another subform. This approach is probably a bit more complex to follow:
<form:form action="${formUrl}" method="post" modelAttribute="organizationUsersForm">
<%-- ... other fields ... --%>
<div id="userSubforms">
<c:forEach items="${organizationUsersForm.users.entrySet()}" var="subformEntry">
<div data-subform-key="${subformEntry.key}">
<spring:nestedPath path="users['${subformEntry.key}']">
<%@ include file="user-subform.jspf" %>
</spring:nestedPath>
</div>
</c:forEach>
</div>
<button onclick="addSubform(jQuery('#userSubforms'), 'users', 'user', 'userTemplate');">ADD ANOTHER USER</button>
<%-- other form fields, submit, etc. --%>
</form:form>
<div class="hide" data-subform-template="user">
<spring:nestedPath path="userTemplate">
<%@ include file="user-subform.jspf" %>
</spring:nestedPath>
</div>
<script>
function addSubform(subformContainer, subformPath, templateName, templatePath) {
// Find the sequence number for the new subform
var existingSubforms = subformContainer.find("[data-subform-key]");
var subformIndex = (existingSubforms.length != 0) ?
parseInt(existingSubforms.last().attr("data-subform-key"), 10) + 1 : 0;
// Create new subform based on the template
var subform = jQuery('<div data-subform-key="' + subformIndex + '" />').
append(jQuery("[data-subform-template=" + templateName + "]").children().clone(true));
// Don't forget to update field names, identifiers and label targets
subform.find("[name]").each(function(node) {
this.name = subformPath + "["+ subformIndex +"]." + this.name;
});
subform.find("[for^=" + templatePath + "]").each(function(node) {
this.htmlFor = this.htmlFor.replace(templatePath + ".", subformPath + "["+ subformIndex +"].");
});
subform.find("[id^=" + templatePath + "]").each(function(node) {
this.id = this.id.replace(templatePath + ".", subformPath + "["+ subformIndex +"].");
});
// Add the new subform to the form
subformContainer.append(subform);
}
</script>
现在您可以问用户如何删除子表单" ?如果子表单JSPF包含以下内容,这将非常容易
Now you can ask "How can user delete a subform"? This is pretty easy if the subform JSPF contains:
<button onclick="jQuery(this).parents('[data-subform-key]').remove();">DELETE USER</button>
这篇关于自动填充集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!