我有以下域类:
机场:
class Airport {
String airportName
List<Flight> flights
static hasMany = [flights: Flight]
static mappedBy = [flights: "departureAirport"]
}
飞行:
class Flight {
String flightName
Integer numOfStaff
Airport departureAirport
}
我在表单中有以下输入字段,可以正确打印已保存的机场及其航班:
<input name="airportName" value="${airportInstance.airportName}" />
<input name="id" value="${airportInstance.id}" />
<input name="version" value="${airportInstance.version}" />
<g:set var="counter" value="${0}" />
<g:each in="${airportInstance?.flights?}" var="f">
<div>
name : <input name="flights[${counter}].flightName" value="${f.flightName}" />
id : <input name="flights[${counter}].id" value="${f.id}" />
numOfStaff : <input name="flights[${counter}].numOfStaff" value="${f.numOfStaff}" />
<g:set var="counter" value="${counter + 1}" />
</div>
</g:each>
我将表单发布到以下控制器操作:
@Transactional
def update() {
Airport airportInstance = Airport.get(params.id)
// doesn't work as well
// airportInstance.properties = params
bindData(airportInstance, params)
airportInstance.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(
code: 'default.updated.message',
args: [
message(
code: 'Airport.label',
default: 'Airport'
),
airportInstance.id
]
)
redirect airportInstance
}
'*'{ respond airportInstance, [status: OK] }
}
}
当我修改airportName或某些航班属性(例如:numOfStaff)并点击更新(将其发布到控制器操作)时,Grails正确地完成了他的工作并更新了我的更改。
但是如果我在视图中手动添加一个新实例,例如:如果有两个航班[0]和航班[1]由g列出:每个我添加航班[2]它不会创建一个新实例飞行并没有保存。 如果我尝试从视图中删除现有航班并将其发布到控制器更新操作,则相同。
我正在使用grails版本2.3.9
我的问题是:
我做错了吗? 是Grails的错误还是Grails开发人员出于某种原因实现了这样的bindData方法? Grails实现上述问题的最佳方式是什么(我的意思是给出名称属性,如foo [index] .prop,其中foo是实体中的集合)。
抱歉垃圾html。 谢谢你们的回答。
答案 0 :(得分:0)
我找到了解决方案。如果我声明一个控制器动作,如:
def update(Airport airport) {
// ...
}
在这种情况下,在执行控制器操作之前,Grails将自动创建Airport类的实例,并通过绑定请求参数来填充其属性。
如果存在id请求参数,则不是调用域类构造函数来创建新实例,而是调用域类上的静态get方法,并将id参数的值作为参数传递。无论从get调用返回什么,都将传递给控制器动作。这意味着如果有一个id请求参数,并且在数据库中找不到相应的记录,那么命令对象的值将为null。
请参阅Grails参考文档:http://grails.org/doc/latest/guide/theWebLayer.html#commandObjects