在我的GSP中,我有一个包含很多文本字段的表单,这些表单由来自控制器的地图填充,让我把它放到一个示例中,因为我的实际形式比这复杂得多:
例如,如果我使用users
填充一堆文字字段,我可以输入每个人的age
,我会将它们分组到一个名为data
的地图中,我想要处理并在提交后保存所有信息:
<g:form useToken="true" name='example_form' action='submit'>
<g:each in='${users}' var='user' status='i'>
<g:textField name="data.${user.id}.name" value="${i.name}">
<g:field name="data.${user.id}.age" value="">
</g:each>
<button>Submit</button>
</g:form>
但是当我在我的submit
控制器中打印出params.data时,我注意到我不仅获得了我创建的data
地图,而且还得到了一堆其中的垃圾:
for(i in params.data){
println "key: ${i.key} value: ${i.value}"
}
输出:
key: 0.name value: john
key: 0 value: [age: 35, name: john]
key: 1.name value: liz
key: 1 value: [age: 24, name: liz]
key: 2.name value: robert
key: 3.name value: david
key: 0.age value: 35
key: 1.age value: 24
key: 2 value: [age: 44, name: robert]
key: 3 value: [age: 23, name: david]
key: 3.age value: 23
key: 2.age value: 44
我做错了吗?
预期产出:
key: 0 value: [age: 35, name: john]
key: 1 value: [age: 24, name: liz]
key: 2 value: [age: 44, name: robert]
key: 3 value: [age: 23, name: david]
答案 0 :(得分:1)
它应该以这种方式工作。当您从表单提交数据时,POST请求的正文就是这样:
data.0.name=john&data.0.age=35&data.1.name=liz&data.1.age=24&data.2.name=robert&data.2.age=44&data.3.name=david&data.3.age=23
所以,它只是一个普通的字符串,表示一个简单的键值映射,Grails可以解析就是这样:
['data.0.name': 'john', 'data.0.age': '35', 'data.1.name': 'liz', 'data.1.age': '24', 'data.2.name': 'robert', 'data.2.age': '44', 'data.3.name': 'david', 'data.3.age': '23']
但Grails开发人员希望简化程序员的生活,他们决定如果密钥包含一个点,则该请求可能代表某种结构化数据。因此除了原始请求数据之外,他们还决定将它放到地图上。因此,点可以用两种方式解释 - 作为普通符号,或作为地图名称和地图键之间的分隔符。这取决于开发人员应该解释点的方式。
答案 1 :(得分:0)
如果您希望使用像def name = params.data.0.name
这样的简单使用更清晰的参数,那么您可以使用“。”来表示“。”。在控制器中,您可以在循环中使用split("_")
。
答案 2 :(得分:0)
在上一篇文章中@Alexander Tokarev解释了发生的事情。解决方案是if语句,如下所示:
for(i in params.data){
if( i.key.isNumber() ) {
println "key: ${i.key} value: ${i.value}"
}
}