列表映射的 Grails 命令对象绑定失败
Grails Command Object binding failing for a Map of Lists
(Grails 版本:2.3.11,Groovy 版本:2.2.2)
我是 Groovy 和 Grails 的新手,如果我遗漏了一些明显的东西,请原谅我。我有一个包含 Map 的命令对象,键是 Integer(虽然我试过 Strings 但它们也不起作用),值是 Details 对象的列表:
class Details {
Integer volume
Double price
}
class TheCommand {
Map<Integer, List<Details>> details = [:].withDefault { [].withLazyDefault { new Details() } }
String location
}
我的 GSP 中有这个:
<g:form controller="mapOfLists" action="create">
<g:textField name="location" size="7"/>
<table>
<g:each in="${(1..24)}" var="hour">
<tr>
<td>${hour}</td>
<g:each in="${(0..4)}" var="column">
<td><g:textField name="details[${hour}][${column}].price" size="4"/></td>
<td><g:textField name="details[${hour}][${column}].volume" size="3"/></td>
</g:each>
</tr>
</g:each>
</table>
<g:submitButton name="Submit" value="Submit"/>
</g:form>
以及操作:
// trying the different binding approaches, none work
def create(TheCommand theCommand) {
// theCommand.hasErrors() -> false
// at this point theCommand's details is an empty map, I can see the details[x][y] values in the params object
bindData(theCommand, params)
// the bindData above didn't work, details is still an empty map
theCommand.properties['details'] = params
// the setting via properties above didn't work, details is still an empty map
}
两个问题:
1)关于尝试什么的任何想法?我已经看到有一种方法可以使用自定义活页夹,但这似乎是 grails 应该处理的情况,所以我在走那条路之前试一试。
2) 是否有更强大的数据绑定器?相关的SimpleDataBinder代码我都看过了,好像只支持单索引属性
非常感谢,
赛斯
如果不借助自定义活页夹,我无法让它工作:(
至于更强大的数据绑定器,有 @BindUsing which allows you to either define a closure or implement the BindingHelper 接口可以将您的输入格式化为您需要的任何格式。您甚至可以在其中使用 GORM 查找器来使用域实例填充属性。
我得到了这么多:
class TheCommand {
@BindUsing({ obj, source ->
def details = new HashMap<Integer, List<Details>>().withDefault { [].withLazyDefault { new Details() } }
source['details']?.collect { mapKey, mapValue ->
if (mapKey.integer) {
mapValue.collect { arrayKey, arrayValue ->
if (arrayKey.integer) {
def detailsObj = new Details(volume:new Integer(arrayValue.volume), price: new Double(arrayValue.price))
details[new Integer(mapKey)].add(new Integer(arrayKey), detailsObj)
}
}
}
}
return details
})
Map<Integer, List<Details>> details
String location
}
适用于以下请求curl http://localhost:8080/test/test/index --data "location=here&details.0.0.volume=20&details.0.0.price=2.2&details.0.1.volume=30&details.0.1.price=2"
它很强大,但很丑陋(虽然我的代码有几个部分可以更好地实现)。我不知道为什么简单的 new Details(arrayValue)
在那里不起作用,但我可能遗漏了一些明显的东西。
(Grails 版本:2.3.11,Groovy 版本:2.2.2)
我是 Groovy 和 Grails 的新手,如果我遗漏了一些明显的东西,请原谅我。我有一个包含 Map 的命令对象,键是 Integer(虽然我试过 Strings 但它们也不起作用),值是 Details 对象的列表:
class Details {
Integer volume
Double price
}
class TheCommand {
Map<Integer, List<Details>> details = [:].withDefault { [].withLazyDefault { new Details() } }
String location
}
我的 GSP 中有这个:
<g:form controller="mapOfLists" action="create">
<g:textField name="location" size="7"/>
<table>
<g:each in="${(1..24)}" var="hour">
<tr>
<td>${hour}</td>
<g:each in="${(0..4)}" var="column">
<td><g:textField name="details[${hour}][${column}].price" size="4"/></td>
<td><g:textField name="details[${hour}][${column}].volume" size="3"/></td>
</g:each>
</tr>
</g:each>
</table>
<g:submitButton name="Submit" value="Submit"/>
</g:form>
以及操作:
// trying the different binding approaches, none work
def create(TheCommand theCommand) {
// theCommand.hasErrors() -> false
// at this point theCommand's details is an empty map, I can see the details[x][y] values in the params object
bindData(theCommand, params)
// the bindData above didn't work, details is still an empty map
theCommand.properties['details'] = params
// the setting via properties above didn't work, details is still an empty map
}
两个问题: 1)关于尝试什么的任何想法?我已经看到有一种方法可以使用自定义活页夹,但这似乎是 grails 应该处理的情况,所以我在走那条路之前试一试。
2) 是否有更强大的数据绑定器?相关的SimpleDataBinder代码我都看过了,好像只支持单索引属性
非常感谢, 赛斯
如果不借助自定义活页夹,我无法让它工作:(
至于更强大的数据绑定器,有 @BindUsing which allows you to either define a closure or implement the BindingHelper 接口可以将您的输入格式化为您需要的任何格式。您甚至可以在其中使用 GORM 查找器来使用域实例填充属性。
我得到了这么多:
class TheCommand {
@BindUsing({ obj, source ->
def details = new HashMap<Integer, List<Details>>().withDefault { [].withLazyDefault { new Details() } }
source['details']?.collect { mapKey, mapValue ->
if (mapKey.integer) {
mapValue.collect { arrayKey, arrayValue ->
if (arrayKey.integer) {
def detailsObj = new Details(volume:new Integer(arrayValue.volume), price: new Double(arrayValue.price))
details[new Integer(mapKey)].add(new Integer(arrayKey), detailsObj)
}
}
}
}
return details
})
Map<Integer, List<Details>> details
String location
}
适用于以下请求curl http://localhost:8080/test/test/index --data "location=here&details.0.0.volume=20&details.0.0.price=2.2&details.0.1.volume=30&details.0.1.price=2"
它很强大,但很丑陋(虽然我的代码有几个部分可以更好地实现)。我不知道为什么简单的 new Details(arrayValue)
在那里不起作用,但我可能遗漏了一些明显的东西。