Grails - 简单的 hasMany 问题 - 在 create.gsp 中使用 CheckBoxes 而不是 HTML Select [英] Grails - Simple hasMany Problem - Using CheckBoxes rather than HTML Select in create.gsp
问题描述
我的问题是:我想创建一个 grails 域实例,定义它拥有的另一个域的许多"实例.我在 Google 代码项目 但下面应该能说明问题.
My problem is this: I want to create a grails domain instance, defining the 'Many' instances of another domain that it has. I have the actual source in a Google Code Project but the following should illustrate the problem.
class Person {
String name
static hasMany[skills:Skill]
static constraints = {
id (visible:false)
skills (nullable:false, blank:false)
}
}
class Skill {
String name
String description
static constraints = {
id (visible:false)
name (nullable:false, blank:false)
description (nullable:false, blank:false)
}
}
如果你对这两个控制器使用这个模型和 def scaffold
那么你最终会得到这样一个不起作用的表单;
If you use this model and def scaffold
for the two Controllers then you end up with a form like this that doesn't work;
我自己尝试让这个工作将技能枚举为复选框,看起来像这样;
My own attempt to get this to work enumerates the Skills as checkboxes and looks like this;
但是当我保存志愿者时,技能无效!
But when I save the Volunteer the skills are null!
这是我保存方法的代码;
This is the code for my save method;
def save = {
log.info "Saving: " + params.toString()
def skills = params.skills
log.info "Skills: " + skills
def volunteerInstance = new Volunteer(params)
log.info volunteerInstance
if (volunteerInstance.save(flush: true)) {
flash.message = "${message(code: 'default.created.message', args: [message(code: 'volunteer.label', default: 'Volunteer'), volunteerInstance.id])}"
redirect(action: "show", id: volunteerInstance.id)
log.info volunteerInstance
}
else {
render(view: "create", model: [volunteerInstance: volunteerInstance])
}
}
这是我的日志输出(我有自定义 toString() 方法);
This is my log output (I have custom toString() methods);
2010-05-10 21:06:41,494 [http-8080-3] INFO bumbumtrain.VolunteerController - Saving: ["skills":["1", "2"], "name":"Ian", "_skills":["", ""], "create":"Create", "action":"save", "controller":"volunteer"]
2010-05-10 21:06:41,495 [http-8080-3] INFO bumbumtrain.VolunteerController - Skills: [1, 2]
2010-05-10 21:06:41,508 [http-8080-3] INFO bumbumtrain.VolunteerController - Volunteer[ id: null | Name: Ian | Skills [Skill[ id: 1 | Name: Carpenter ] , Skill[ id: 2 | Name: Sound Engineer ] ]]
请注意,在最后的日志行中,正确的技能已被拾取并且是对象实例的一部分.当志愿者被保存时,技能"被忽略并且没有提交到数据库中,尽管创建的内存版本清楚地确实有这些项目.施工时不能通过技能吗?一定有办法解决这个问题?我需要一个表格来允许一个人注册,但我想规范化数据,以便以后添加更多技能.
Note that in the final log line the right Skills have been picked up and are part of the object instance. When the volunteer is saved the 'Skills' are ignored and not commited to the database despite the in memory version created clearly does have the items. Is it not possible to pass the Skills at construction time? There must be a way round this? I need a single form to allow a person to register but I want to normalise the data so that I can add more skills at a later time.
如果您认为这应该正常工作",那么一个工作示例的链接会很棒.
If you think this should 'just work' then a link to a working example would be great.
如果我使用 HTML Select 则可以正常工作!如下所示制作创建页面;
If I use the HTML Select then it works fine! Such as the following to make the Create page;
<tr class="prop">
<td valign="top" class="name">
<label for="skills"><g:message code="volunteer.skills.label" default="Skills" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: volunteerInstance, field: 'skills', 'errors')}">
<g:select name="skills" from="${uk.co.bumbumtrain.Skill.list()}" multiple="yes" optionKey="id" size="5" value="${volunteerInstance?.skills}" />
</td>
</tr>
但我需要它来处理这样的复选框;
<tr class="prop">
<td valign="top" class="name">
<label for="skills"><g:message code="volunteer.skills.label" default="Skills" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: volunteerInstance, field: 'skills', 'errors')}">
<g:each in="${skillInstanceList}" status="i" var="skillInstance">
<label for="${skillInstance?.name}"><g:message code="${skillInstance?.name}.label" default="${skillInstance?.name}" /></label>
<g:checkBox name="skills" value="${skillInstance?.id.toString()}"/>
</g:each>
</td>
</tr>
日志输出完全相同! 使用这两种样式的表单,创建志愿者实例时使用在技能"变量中正确引用的技能.保存时,后者失败并出现空引用异常,如本问题顶部所示.
The log output is exactly the same! With both style of form the Volunteer instance is created with the Skills correctly referenced in the 'Skills' variable. When saving, the latter fails with a null reference exception as shown at the top of this question.
希望这是有道理的,在此先感谢!
Hope this makes sense, thanks in advance!
Gav
推荐答案
将你的 create.gsp <g:checkbox...>
代码替换为:
Replace your create.gsp <g:checkbox...>
code by:
<g:checkBox name="skill_${skillInstance.id}"/>
然后在控制器的 save
操作中,将 def VolunteerInstance = new Volunteer(params)
替换为:
Then inside the save
action of your controller, replace def volunteerInstance = new Volunteer(params)
by :
def volunteerInstance = new Volunteer(name: params.name)
params.each {
if (it.key.startsWith("skill_"))
volunteerInstance.skills << Skill.get((it.key - "skill_") as Integer)
}
应该可以.(代码未测试)
Should work. (code not tested)
这篇关于Grails - 简单的 hasMany 问题 - 在 create.gsp 中使用 CheckBoxes 而不是 HTML Select的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!