【问题标题】:Passing parameters to a form grails将参数传递给表单 grails
【发布时间】:2017-04-12 04:50:17
【问题描述】:

我是 grails 的新手,我正在尝试将对象 ID 传递给表单。我有名为 Beer 和 recipe 的域。啤酒有很多食谱和食谱都属于啤酒。我想从啤酒展示页面创建一个指向新配方的链接,并在 url 中传递啤酒 id 以创建关联。现在我一直在尝试使用此链接<g:link controller="recpie" action="create" params="[beerid: selectedBeer.id]">Create Recipe</g:link> 并在表单中将其检索为隐藏字段,以使用<g:field type="text" name="beer.id" value="${beer}"/>. 与配方表单一起提交(我知道隐藏属性未设置)。我究竟做错了什么?还有没有更好的方法来创建这个关联?

啤酒领域类

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

啤酒/表演 GSP

    <!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>

** 配方/创建 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>

【问题讨论】:

    标签: grails gsp


    【解决方案1】:

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

    beer - show.gsp

    <g:link controller="recipe" action="create" resource="recipe" params="[beerid: beer.id]">Create Recipe</g:link>
    

    recpie - create.gsp

    <g:hiddenField name="beer.id" value="${params.beerid}"/>
    

    【讨论】:

    • 在我的啤酒秀中,我无法解析符号 selectedBeer.id。我假设我的控制器中缺少一些东西。我只有在表演动作中响应啤酒。据我了解,应该将啤酒对象发送到正确的视图?
    • 您如何将数据输入啤酒秀 gsp?在地图中?啤酒域实例的名称是否选中Beer?
    • 啤酒域对象上的其他字段如何显示?
    • 更新答案,gsp中使用beer而不是selectedBeer作为域名
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-13
    • 1970-01-01
    • 2013-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多