在实体字段和属性中使用集合时如何使用Grails bindData

时间:2014-07-21 23:38:24

标签: grails

我有以下域类:

机场:

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。 谢谢你们的回答。

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。如果我声明一个控制器动作,如:

def update(Airport airport) {
  // ...
}

在这种情况下,在执行控制器操作之前,Grails将自动创建Airport类的实例,并通过绑定请求参数来填充其属性。

如果存在id请求参数,则不是调用域类构造函数来创建新实例,而是调用域类上的静态get方法,并将id参数的值作为参数传递。无论从get调用返回什么,都将传递给控制器​​动作。这意味着如果有一个id请求参数,并且在数据库中找不到相应的记录,那么命令对象的值将为null。

请参阅Grails参考文档:http://grails.org/doc/latest/guide/theWebLayer.html#commandObjects