Grails 在创建域对象之前将子元素添加到域对象

Grails 在创建域对象之前将子元素添加到域对象,grails,grails-2.1,Grails,Grails 2.1,(很抱歉,如果这是一个noob问题,我无法在上找到答案) 我拥有以下域继承权: 用户>(有很多)调查>(有很多)调查问题>(有很多)调查问题回答 这是上述两项: class Survey { String surveyName static hasMany = [questions: SurveyQuestion] static belongsTo = [user:User] static constraints = { } } class Surv

(很抱歉,如果这是一个noob问题,我无法在上找到答案)

我拥有以下域继承权:

用户>(有很多)调查>(有很多)调查问题>(有很多)调查问题回答

这是上述两项:

class Survey {

    String surveyName

    static hasMany = [questions: SurveyQuestion]
    static belongsTo = [user:User]
    static constraints = {
    }
}

class SurveyQuestion {

    String question

    static hasMany = [responses : SurveyQuestionResponse]
    static belongsTo = [survey:Survey]

    static constraints = {
    }
}
创建调查时,我首先看到如下屏幕:

我填写调查名称,然后单击添加调查问题,然后查看下一个屏幕:

但这需要进行一次调查,调查尚未完成

问题:我是否必须先创建和保存调查,然后编辑调查并添加调查问题(在创建答复之前,每个问题都需要单独创建和保存),或者在创建父对象时是否有方法添加子对象

我想使用动态脚手架,这样我就不必手动创建控制器和视图


问题和答案完全独立,不会在整个层次结构中重复使用。

使用该用户界面,您应该创建、保存和添加。更好的方法是创建主/详细用户界面。你可以在这里看到这种方法:


如果要重复使用这些问题。。。也许你不应该使用belongsTo=[调查:调查]


然后,如果没有此关系,则可以创建用于创建问题的模板,并在保存之前将其添加到调查对象中的问题集合中

您应该使用命令对象。这样,您可以在创建父元素时轻松地添加子元素。例如

class CreateSurveyCommand {
     String surveyName
     List<SurveyQuestion> surveyQuestions = 
         org.apache.commons.collections.list.LazyList.decorate(
             new ArrayList(), 
             new org.apache.commons.collections.functors.InstantiateFactory(SurveyQuestion.class))
}
在控制器中执行
addQuestion
操作:

def addAction(CreateSurveyCommand cmd) {
    cmd.surveyQuestions.add(new SurveyQuestion())
    render(view:"index", model: [cmd: cmd])
}
编辑是另一个主题,但工作方式相同

看看这篇博文:


如果您在
调查
类中将
问题
声明为
列表
,则您的视图将能够通过索引访问这些问题

List questions
static hasMany = [questions: SurveyQuestion]
在GSP表格中,您可以使用以下内容:

<g:textField
    name="questions[0].question"
    value="${surveyInstance?.questions?.size() > 0 ? surveyInstance?.questions[0]?.question : ''}"/>

值的三元组有点粗糙,但可以很容易地隐藏在您自己的标记中

如果确实需要使用动态支架,可以覆盖单个视图或用于生成视图的模板。或者,您可以使用呈现
问题
属性的输入

我创建了一个简单的应用程序&在这一点上,一切似乎都正常工作。我本来希望必须编写一个
PropertyEditor
实现来扩展列表,但Grails2.1似乎可以为您做到这一点


重新排序或删除问题需要更多的实验,但更新问题会起作用,即问题文本会发生更改,而不是创建新的
SurveyQuestion
实例。

听起来像是,您希望保存调查。或者,您可以将所有这些设置为流,并删除编辑页面的“选择父项”部分。流对于多页创建过程很好。拜托,兄弟,你读过答案了吗?您应该使用命令对象和一个用LazyList装饰的集合,最好是javascript/jquery。你想要我的朋友做什么?你应该在配方中添加一个服务,以获得交易支持来澄清。我个人会像@crudolf建议的那样使用命令对象,或者全力以赴使用更丰富的前端,比如Angular,但如果你决定使用scaffolding,这可能会对你有用。这看起来是迄今为止最可行的选择,但它确实取决于使用静态scaffolding(或者至少自己实现某种形式的视图)。我问的原因是因为我更喜欢使用动态脚手架;更少的编码、更少的维护和更少的工作量;)(理论上,总有一个陷阱)
<g:textField
    name="questions[0].question"
    value="${surveyInstance?.questions?.size() > 0 ? surveyInstance?.questions[0]?.question : ''}"/>