我有一个包含问题和答案的应用程序(请参阅下面列出的域)。基本上,问题has many
会回答。每个答案都有一个ordinal
,用于确定答案的显示顺序。我希望表单允许用户更改序数。我的问题是,我不确定如何将html表单中的输入字段与服务器端的正确答案相关联。当我提交此表格时
<g:if test="${questionInstance.answers}">
<div class="control-group">
<label class="control-label">Order</label>
<div class="controls">
<g:each status="i" in="${questionInstance.answers}" var="answer">
<div><input type="text" name="answer[${i}].id" style="width:15px;" value="${answer?.ordinal}" />
${answer.body}
</div>
</g:each>
</div>
</div>
</g:if>
我在update
动作question
控制器上获得了这些参数(控制器显示在底部)。我想更新每个答案的序数但不确定如何
class Question {
DateTime dateCreated
DateTime lastUpdated
String body
Answer correctAnswer
Integer ordinal
static belongsTo = [lesson: Lesson]
static hasMany = [answers: Answer]
static constraints = {
body blank: false
correctAnswer nullable: true,
validator: { Answer val, Question obj ->
// Correct answer must have this as it's question
val ? val.question == obj : true // TODO: Give this a proper error message
}
ordinal unique: 'lesson'
}
static mapping = {
lesson lazy: true
answers sort: 'ordinal'
answers cascade: 'all-delete-orphan'
}
}
class Answer {
DateTime dateCreated
DateTime lastUpdated
String body
Integer ordinal
String reason
static belongsTo = [question: Question]
static constraints = {
body blank: false
ordinal unique: 'question'
}
static mapping = {
question lazy: true
}
String toString() {
"Answer: $body"
}
Integer getNextOrdinal() {
Integer ordinal = Answer.createCriteria().get {
projections {
max "ordinal"
}
}
ordinal = ordinal ?: 1
return ordinal
}
}
def update(Long id, Long version) {
def questionInstance = Question.get(id)
if (!questionInstance) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'question.label', default: 'Question'), id])
redirect(action: "lessonQuestionDashBoard", controller: "lesson")
return
}
if (version != null) {
if (questionInstance.version > version) {
questionInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
[message(code: 'question.label', default: 'Question')] as Object[],
"Another user has updated this Question while you were editing")
render(view: "edit", model: [questionInstance: questionInstance])
return
}
}
questionInstance.properties = params
if (!questionInstance.save(flush: true)) {
render(view: "edit", model: [questionInstance: questionInstance])
return
}
flash.message = "Question: '${questionInstance.body}' has been updated"
flash.messageType = "success"
redirect(action: "show", id: questionInstance.id)
}
答案 0 :(得分:0)
如docs about data binding所述(正如Martin已经提到的那样),你必须编辑如下的表单元素:
<g:if test="${questionInstance.answers}">
<g:each status="i" in="${questionInstance.answers}" var="answer">
<input type="text" name="answer[${i}].ordinal" value="${answer?.ordinal}" />
<input type="hidden" name="answer[${i}].id" value="${answer?.id}" />
</g:each>
</g:if>
这是因为你从问题到答案的hasMany关系来自类型Set。 Whit这个构造params看起来像这样:
params[answer][0] = [id: 123, ordinal: 4]
等等。这样,数据绑定将按预期工作。