将表单中的http请求参数与对象集合相关联

时间:2014-08-01 19:13:01

标签: grails groovy

我有一个包含问题和答案的应用程序(请参阅下面列出的域)。基本上,问题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控制器上获得了这些参数(控制器显示在底部)。我想更新每个答案的序数但不确定如何

parameters

问题对象

问题域

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)
}

1 个答案:

答案 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]

等等。这样,数据绑定将按预期工作。