将参数传递给grails表单

将参数传递给grails表单,grails,gsp,Grails,Gsp,我是grails新手,我正在尝试将对象Id传递给表单。我有一个叫做啤酒和食谱的域名。啤酒有许多配方,配方属于啤酒。我想从啤酒秀页面创建一个指向新配方的链接,在url中传递啤酒id,以便创建关联。目前,我一直在尝试使用此链接创建配方,并在表单中检索它作为隐藏字段,以便使用与配方表单一起提交(我知道未设置隐藏属性)。我做错了什么?还有没有更好的方法来创建此关联 啤酒领域类 class Beer { String name String style Recipe recipe

我是grails新手,我正在尝试将对象Id传递给表单。我有一个叫做啤酒和食谱的域名。啤酒有许多配方,配方属于啤酒。我想从啤酒秀页面创建一个指向新配方的链接,在url中传递啤酒id,以便创建关联。目前,我一直在尝试使用此链接
创建配方
,并在表单中检索它作为隐藏字段,以便使用
与配方表单一起提交(我知道未设置隐藏属性)。我做错了什么?还有没有更好的方法来创建此关联

啤酒领域类

class Beer {

    String name
    String style
    Recipe recipe

    String toString() {
        name
    }

    static hasMany = [recipe : Recipe]


    static constraints = {
    }
}
class Recipe {

    String name
    Float grainAmount
    String yeast
    float boilTime
    Float hopAmount
    float og
    float fg
    float ogTemp
    float fgTemp
    float fermTime
    Beer beer


    static belongsTo = [ beer: Beer]

    static constraints = {
        beer nullable: true
    }

    String toString() {
        name
    }
 }
配方域类

class Beer {

    String name
    String style
    Recipe recipe

    String toString() {
        name
    }

    static hasMany = [recipe : Recipe]


    static constraints = {
    }
}
class Recipe {

    String name
    Float grainAmount
    String yeast
    float boilTime
    Float hopAmount
    float og
    float fg
    float ogTemp
    float fgTemp
    float fermTime
    Beer beer


    static belongsTo = [ beer: Beer]

    static constraints = {
        beer nullable: true
    }

    String toString() {
        name
    }
 }
啤酒控制器

package com.example

import static org.springframework.http.HttpStatus.*
import grails.transaction.Transactional

@Transactional(readOnly = true)
class BeerController {

    static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]

    def index(Integer max) {
        params.max = Math.min(max ?: 10, 100)
        respond Beer.list(params), model:[beerCount: Beer.count()]
    }

    def show(Beer beer) {

        respond beer
    }

    def create() {
        respond new Beer(params)
    }

    @Transactional
    def save(Beer beer) {
        if (beer == null) {
            transactionStatus.setRollbackOnly()
            notFound()
            return
        }

        if (beer.hasErrors()) {
            transactionStatus.setRollbackOnly()
            respond beer.errors, view:'create'
            return
        }

        beer.save flush:true

        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.created.message', args: [message(code: 'beer.label', default: 'Beer'), beer.id])
                redirect beer
            }
            '*' { respond beer, [status: CREATED] }
        }
    }

    def edit(Beer beer) {
        respond beer
    }

    @Transactional
    def update(Beer beer) {
        if (beer == null) {
            transactionStatus.setRollbackOnly()
            notFound()
            return
        }

        if (beer.hasErrors()) {
            transactionStatus.setRollbackOnly()
            respond beer.errors, view:'edit'
            return
        }

        beer.save flush:true

        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.updated.message', args: [message(code: 'beer.label', default: 'Beer'), beer.id])
                redirect beer
            }
            '*'{ respond beer, [status: OK] }
        }
    }

    @Transactional
    def delete(Beer beer) {

        if (beer == null) {
            transactionStatus.setRollbackOnly()
            notFound()
            return
        }

        beer.delete flush:true

        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.deleted.message', args: [message(code: 'beer.label', default: 'Beer'), beer.id])
                redirect action:"index", method:"GET"
            }
            '*'{ render status: NO_CONTENT }
        }
    }

    protected void notFound() {
        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.not.found.message', args: [message(code: 'beer.label', default: 'Beer'), params.id])
                redirect action: "index", method: "GET"
            }
            '*'{ render status: NOT_FOUND }
        }
    }
}
package com.example

import static org.springframework.http.HttpStatus.*
import grails.transaction.Transactional

@Transactional(readOnly = true)
class RecipeController {

    static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]

    def index(Integer max) {
        params.max = Math.min(max ?: 10, 100)
        respond Recipe.list(params), model:[recipeCount: Recipe.count()]
    }

    def show(Recipe recipe) {
        respond recipe
    }

    def create() {
        respond new Recipe(params)
    }

    @Transactional
    def save(Recipe recipe) {
        if (recipe == null) {
            transactionStatus.setRollbackOnly()
            notFound()
            return
        }

        if (recipe.hasErrors()) {
            transactionStatus.setRollbackOnly()
            respond recipe.errors, view:'create'
            return
        }

        recipe.save flush:true

        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.created.message', args: [message(code: 'recipe.label', default: 'Recipe'), recipe.id])
                redirect recipe
            }
            '*' { respond recipe, [status: CREATED] }
        }
    }

    def edit(Recipe recipe) {
        respond recipe
    }

    @Transactional
    def update(Recipe recipe) {
        if (recipe == null) {
            transactionStatus.setRollbackOnly()
            notFound()
            return
        }

        if (recipe.hasErrors()) {
            transactionStatus.setRollbackOnly()
            respond recipe.errors, view:'edit'
            return
        }

        recipe.save flush:true

        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.updated.message', args: [message(code: 'recipe.label', default: 'Recipe'), recipe.id])
                redirect recipe
            }
            '*'{ respond recipe, [status: OK] }
        }
    }

    @Transactional
    def delete(Recipe recipe) {

        if (recipe == null) {
            transactionStatus.setRollbackOnly()
            notFound()
            return
        }

        recipe.delete flush:true

        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.deleted.message', args: [message(code: 'recipe.label', default: 'Recipe'), recipe.id])
                redirect action:"index", method:"GET"
            }
            '*'{ render status: NO_CONTENT }
        }
    }

    protected void notFound() {
        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.not.found.message', args: [message(code: 'recipe.label', default: 'Recipe'), params.id])
                redirect action: "index", method: "GET"
            }
            '*'{ render status: NOT_FOUND }
        }
    }
}
配方控制器

package com.example

import static org.springframework.http.HttpStatus.*
import grails.transaction.Transactional

@Transactional(readOnly = true)
class BeerController {

    static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]

    def index(Integer max) {
        params.max = Math.min(max ?: 10, 100)
        respond Beer.list(params), model:[beerCount: Beer.count()]
    }

    def show(Beer beer) {

        respond beer
    }

    def create() {
        respond new Beer(params)
    }

    @Transactional
    def save(Beer beer) {
        if (beer == null) {
            transactionStatus.setRollbackOnly()
            notFound()
            return
        }

        if (beer.hasErrors()) {
            transactionStatus.setRollbackOnly()
            respond beer.errors, view:'create'
            return
        }

        beer.save flush:true

        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.created.message', args: [message(code: 'beer.label', default: 'Beer'), beer.id])
                redirect beer
            }
            '*' { respond beer, [status: CREATED] }
        }
    }

    def edit(Beer beer) {
        respond beer
    }

    @Transactional
    def update(Beer beer) {
        if (beer == null) {
            transactionStatus.setRollbackOnly()
            notFound()
            return
        }

        if (beer.hasErrors()) {
            transactionStatus.setRollbackOnly()
            respond beer.errors, view:'edit'
            return
        }

        beer.save flush:true

        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.updated.message', args: [message(code: 'beer.label', default: 'Beer'), beer.id])
                redirect beer
            }
            '*'{ respond beer, [status: OK] }
        }
    }

    @Transactional
    def delete(Beer beer) {

        if (beer == null) {
            transactionStatus.setRollbackOnly()
            notFound()
            return
        }

        beer.delete flush:true

        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.deleted.message', args: [message(code: 'beer.label', default: 'Beer'), beer.id])
                redirect action:"index", method:"GET"
            }
            '*'{ render status: NO_CONTENT }
        }
    }

    protected void notFound() {
        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.not.found.message', args: [message(code: 'beer.label', default: 'Beer'), params.id])
                redirect action: "index", method: "GET"
            }
            '*'{ render status: NOT_FOUND }
        }
    }
}
package com.example

import static org.springframework.http.HttpStatus.*
import grails.transaction.Transactional

@Transactional(readOnly = true)
class RecipeController {

    static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]

    def index(Integer max) {
        params.max = Math.min(max ?: 10, 100)
        respond Recipe.list(params), model:[recipeCount: Recipe.count()]
    }

    def show(Recipe recipe) {
        respond recipe
    }

    def create() {
        respond new Recipe(params)
    }

    @Transactional
    def save(Recipe recipe) {
        if (recipe == null) {
            transactionStatus.setRollbackOnly()
            notFound()
            return
        }

        if (recipe.hasErrors()) {
            transactionStatus.setRollbackOnly()
            respond recipe.errors, view:'create'
            return
        }

        recipe.save flush:true

        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.created.message', args: [message(code: 'recipe.label', default: 'Recipe'), recipe.id])
                redirect recipe
            }
            '*' { respond recipe, [status: CREATED] }
        }
    }

    def edit(Recipe recipe) {
        respond recipe
    }

    @Transactional
    def update(Recipe recipe) {
        if (recipe == null) {
            transactionStatus.setRollbackOnly()
            notFound()
            return
        }

        if (recipe.hasErrors()) {
            transactionStatus.setRollbackOnly()
            respond recipe.errors, view:'edit'
            return
        }

        recipe.save flush:true

        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.updated.message', args: [message(code: 'recipe.label', default: 'Recipe'), recipe.id])
                redirect recipe
            }
            '*'{ respond recipe, [status: OK] }
        }
    }

    @Transactional
    def delete(Recipe recipe) {

        if (recipe == null) {
            transactionStatus.setRollbackOnly()
            notFound()
            return
        }

        recipe.delete flush:true

        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.deleted.message', args: [message(code: 'recipe.label', default: 'Recipe'), recipe.id])
                redirect action:"index", method:"GET"
            }
            '*'{ render status: NO_CONTENT }
        }
    }

    protected void notFound() {
        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.not.found.message', args: [message(code: 'recipe.label', default: 'Recipe'), params.id])
                redirect action: "index", method: "GET"
            }
            '*'{ render status: NOT_FOUND }
        }
    }
}
啤酒/表演普惠制

    <!DOCTYPE html>
    <html>
        <head>
            <meta name="layout" content="main" />
            <g:set var="entityName" value="${message(code: 'beer.label', default: 'Beer')}" />
            <title><g:message code="default.show.label" args="[entityName]" /></title>
        </head>
        <body>
            <a href="#show-beer" class="skip" tabindex="-1"><g:message code="default.link.skip.label" default="Skip to content&hellip;"/></a>
            <div class="nav" role="navigation">
                <ul>
                    <li><a class="home" href="${createLink(uri: '/')}"><g:message code="default.home.label"/></a></li>
                    <li><g:link class="list" action="index"><g:message code="default.list.label" args="[entityName]" /></g:link></li>
                    <li><g:link class="list" action="create" resource="recipe">New Recipe</g:link></li>
                </ul>
            </div>
            <div id="show-beer" class="content scaffold-show" role="main">
                <h1><g:message code="default.show.label" args="[entityName]" /></h1>
                <g:if test="${flash.message}">
                <div class="message" role="status">${flash.message}</div>
                </g:if>
                <g:link controller="recpie" action="create" resource="recipe" params="[beerid: selectedBeer.id]">Create Recipe</g:link>
                <f:display bean="beer" />
                <g:form resource="${this.beer}" method="DELETE">
                    <fieldset class="buttons">
                        <g:link class="edit" action="edit" resource="${this.beer}"><g:message code="default.button.edit.label" default="Edit" /></g:link>
                        <input class="delete" type="submit" value="${message(code: 'default.button.delete.label', default: 'Delete')}" onclick="return confirm('${message(code: 'default.button.delete.confirm.message', default: 'Are you sure?')}');" />
                    </fieldset>
                </g:form>
            </div>
        </body>
    </html>

  • 新配方
${flash.message} 创建配方
**配方/创建GSP**

<%@ page import="com.example.Beer" %>
<!DOCTYPE html>
<html>
    <head>
        <meta name="layout" content="main" />
        <g:set var="entityName" value="${message(code: 'recipe.label', default: 'Recipe')}" />
        <title><g:message code="default.create.label" args="[entityName]" /></title>
    </head>
    <body>
        <a href="#create-recipe" class="skip" tabindex="-1"><g:message code="default.link.skip.label" default="Skip to content&hellip;"/></a>
        <div class="nav" role="navigation">
            <ul>
                <li><a class="home" href="${createLink(uri: '/')}"><g:message code="default.home.label"/></a></li>
                <li><g:link class="list" action="index"><g:message code="default.list.label" args="[entityName]" /></g:link></li>
            </ul>
        </div>
        <div id="create-recipe" class="content scaffold-create" role="main">
            <h1><g:message code="default.create.label" args="[entityName]" /></h1>
            <g:if test="${flash.message}">
            <div class="message" role="status">${flash.message}</div>
            </g:if>
            <g:hasErrors bean="${this.recipe}">
            <ul class="errors" role="alert">
                <g:eachError bean="${this.recipe}" var="error">
                <li <g:if test="${error in org.springframework.validation.FieldError}">data-field-id="${error.field}"</g:if>><g:message error="${error}"/></li>
                </g:eachError>
            </ul>
            </g:hasErrors>
            <g:form action="save" name="recipeForm">
                <fieldset class="form">
                    Name:
                    <g:field type="text" name="name"/>
                    Grain Amount:
                    <g:field type="text" name="grainAmount"/>
                    Yeast:
                    <g:field type="text" name="yeast"/>
                    Boil Time:
                    <g:field type="text" name="boilTime"/>
                    Hop Amount:
                    <g:field type="text" name="hopAmount"/>
                    OG:
                    <g:field type="text" name="og"/>
                    FG:
                    <g:field type="text" name="fg"/>
                    OG Temp:
                    <g:field type="text" name="ogTemp"/>
                    FG Temp:
                    <g:field type="text" name="fgTemp"/>
                    Ferment Time:
                    <g:field type="text" name="fermTime"/>
                    beer:
                    <g:hiddenField name="beerid" value="${params.beerid}" />


                </fieldset>

                <fieldset class="buttons">
                    <g:submitButton name="create" class="save" value="${message(code: 'default.button.create.label', default: 'Create')}" />
                </fieldset>
            </g:form>
        </div>
    </body>
</html>

${flash.message}
姓名: 粮食数量: 酵母: 煮沸时间: 跳数: OG: 前景: OG温度: FG温度: 发酵时间: 啤酒:
您已经从名为beerid的啤酒秀页面提交了啤酒ID,因此您需要从配方创建页面上的参数中检索啤酒ID,如下所示:

beer-show.gsp

<g:link controller="recipe" action="create" resource="recipe" params="[beerid: beer.id]">Create Recipe</g:link>
<g:hiddenField name="beer.id" value="${params.beerid}"/>

您已从名为beerid的啤酒秀页面提交了啤酒ID,因此需要从配方创建页面上的参数中检索该啤酒ID,如下所示:

beer-show.gsp

<g:link controller="recipe" action="create" resource="recipe" params="[beerid: beer.id]">Create Recipe</g:link>
<g:hiddenField name="beer.id" value="${params.beerid}"/>

在我的啤酒秀中,我无法解析symbol selectedBeer.id。我想我的控制器中缺少了什么。我在表演中只有啤酒。据我所知,应该将啤酒对象发送到正确的视图?您如何将数据输入啤酒展gsp?在地图上?啤酒域实例的名称是否为selectedBeer?啤酒域对象上的其他字段如何显示?更新了答案,在gspLet us中使用啤酒而不是selectedBeer作为域名。在我的啤酒秀中,我无法解析symbol selectedBeer.id。我想我的控制器中缺少了什么。我在表演中只有啤酒。据我所知,应该将啤酒对象发送到正确的视图?您如何将数据输入啤酒展gsp?在地图上?beer域实例的名称是否selectedBeer?其他字段如何显示在beer域对象上?更新了答案,在gspLet us中使用beer而不是selectedBeer作为域名。