2017-04-12 63 views
0

我是新来的grails我想通过一个对象Id到窗体。我有域名叫啤酒和食谱。啤酒有很多食谱和食谱属于啤酒。我想创建一个链接到啤酒展示页面的新配方,通过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}"/>.(我知道未设置隐藏属性)与配方表单一起提交。我究竟做错了什么?还有更好的方法来创建这种关联?将参数传递给一个窗体grails

啤酒域类

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> 

回答

1

你已经从啤酒提交的啤酒ID显示分页名为beerid,因此您需要从recpie创建页面上的参数中检索它,例如:

beer - show.gsp

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

recpie - create.gsp

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

在我的啤酒展示我得到不能不能解决符号selectedBeer.id。我假设我在我的控制器中丢失了一些东西。我只有在节目中回应啤酒。根据我的理解,应该将啤酒物品发送到正确的视图? – Taylor

+1

你如何向你的啤酒节目gsp提供数据?在地图上?啤酒域实例的名称是selectedBeer吗? –

+0

我的控制器是这个def show(啤酒啤酒){响应啤酒}我认为这将是足够的,因为它是在一个啤酒实例发送。 – Taylor