【问题标题】:How to create dynamic button in grails如何在grails中创建动态按钮
【发布时间】:2017-01-16 21:12:28
【问题描述】:

我正在尝试使用这种逻辑创建一些应用程序;

我有汽车条目,我想在我的汽车列表中的每个条目中添加(租用)按钮,何时单击按钮某人,按钮将打开一些表格以获取条目联系信息,此表格应获取汽车 ID自动编号

这是我的汽车领域类。我不明白如何将按钮添加到我的 index.gsp 中,其中列出了我关于汽车的条目以及如何从列表中获取所选汽车的 ID 号并发送到表单

如何做到这一点?这个逻辑是如何工作的?

package rentme

class Car {

    String brand
    String model
    String fuelType
    BigDecimal pricePerDay
    String busy

    static constraints = {
        brand(inList:["AUDI", "BMW", "MERCEDES", "NISSAN", "HONDA", "FORD"])
        fuelType(inList:["FUEL", "DIESEL", "AUTOGAS"])
        pricePerDay(min:0.0, max:1000.0)
        busy(inList:["YES", "NO"])
    }
}

这是我尝试过的;

这是我在视图文件中的 Car/index.gsp。 - 在这里,我得到了汽车 ID,并试图将按钮放在每个 ID 上。我想做这个;按钮将转到另一个页面,该页面将是租用此车的注册页面,在此注册页面中,用户将看到选择的汽车的 ID 号。

  <g:each in="${carList}" var="car">
                    <p>${car.id} </p>
                    <g:link action="registration" controller="registration" params="[carId : ${car.id} ]">
                        Rent Car
                    </g:link>

                </g:each>

这是我的注册类的域类

包租我

class Registration {

    String yourName

    static constraints = {
        yourName()
    }
}

这是我的注册控制器,我使用 generate-all 命令创建它

package rentme

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

@Transactional(readOnly = true)
class RegistrationController {

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

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

    def show(Registration registration) {
        respond registration
        println params
        Car b = Car.get(params.id)
    }

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

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

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

        registration.save flush:true

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

    def edit(Registration registration) {
        respond registration
    }

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

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

        registration.save flush:true

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

    @Transactional
    def delete(Registration registration) {

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

        registration.delete flush:true

        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.deleted.message', args: [message(code: 'registration.label', default: 'Registration'), registration.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: 'registration.label', default: 'Registration'), params.id])
                redirect action: "index", method: "GET"
            }
            '*'{ render status: NOT_FOUND }
        }
    }
}

我在 def show() 方法中添加了这行代码用于获取 car.id

 def show(Registration registration) {
        respond registration
        println params
        Car b = Car.get(params.id)
    }

这是我在视图registration/index.gsp中的注册页面

<!DOCTYPE html>
<html>
    <head>
        <meta name="layout" content="main" />
        <g:set var="entityName" value="${message(code: 'registration.label', default: 'Registration')}" />
        <title><g:message code="default.list.label" args="[entityName]" /></title>
    </head>
    <body>
        <a href="#list-registration" 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="create" action="create"><g:message code="default.new.label" args="[entityName]" /></g:link></li>
            </ul>
        </div>
        <div id="list-registration" class="content scaffold-list" role="main">
            <h1><g:message code="default.list.label" args="[entityName]" /></h1>
            <g:if test="${flash.message}">
                <div class="message" role="status">${flash.message}</div>
            </g:if>
            <f:table collection="${registrationList}" />

            <div class="pagination">
                <g:paginate total="${registrationCount ?: 0}" />
            </div>


            <div><p>${car.id} </p></div>
        </div>
    </body>
</html>

我在此处添加了此代码以获取 car.id

 <div><p>${car.id} </p></div>


Error 500: Internal Server Error
URI
/car/index
Class
org.grails.taglib.GrailsTagException
Message
Request processing failed; nested exception is java.lang.RuntimeException: Error initializing GroovyPageView
Caused by
[views/car/index.gsp:32] Attribute value quote wasn't closed (action="registration" controller="registration" params="[carId : ${car.id} ]").

I don't know this method is good or not but i get this error when i open on browser my registration index page 

    Line | Method
->>  223 | createGroovyPageView  in org.grails.web.servlet.view.GroovyPageViewResolver
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    200 | createGrailsView      in     ''
|     99 | loadView . . . . . .  in     ''
|     36 | loadView              in grails.plugin.scaffolding.ScaffoldingViewResolver
|    244 | createView . . . . .  in org.springframework.web.servlet.view.AbstractCachingViewResolver
|    472 | createView            in org.springframework.web.servlet.view.UrlBasedViewResolver
|    146 | resolveViewName . . . in org.springframework.web.servlet.view.AbstractCachingViewResolver
|     88 | resolveViewName       in org.grails.web.servlet.view.GroovyPageViewResolver
|     57 | resolveViewName . . . in org.grails.web.servlet.view.GrailsLayoutViewResolver
|   1296 | resolveViewName       in org.springframework.web.servlet.DispatcherServlet
|   1234 | render . . . . . . .  in     ''
|   1037 | processDispatchResult in     ''
|    980 | doDispatch . . . . .  in     ''
|    897 | doService             in     ''
|    970 | processRequest . . .  in org.springframework.web.servlet.FrameworkServlet
|    861 | doGet                 in     ''
|    622 | service . . . . . . . in javax.servlet.http.HttpServlet
|    846 | service               in org.springframework.web.servlet.FrameworkServlet
|    729 | service . . . . . . . in javax.servlet.http.HttpServlet
|    230 | internalDoFilter      in org.apache.catalina.core.ApplicationFilterChain
|    165 | doFilter . . . . . .  in     ''
|     52 | doFilter              in org.apache.tomcat.websocket.server.WsFilter
|    192 | internalDoFilter . .  in org.apache.catalina.core.ApplicationFilterChain
|    165 | doFilter              in     ''
|     55 | doFilterInternal . .  in org.springframework.boot.web.filter.ApplicationContextHeaderFilter
|    107 | doFilter              in org.springframework.web.filter.OncePerRequestFilter
|    192 | internalDoFilter . .  in org.apache.catalina.core.ApplicationFilterChain
|    165 | doFilter              in     ''
|    105 | doFilterInternal . .  in org.springframework.boot.actuate.trace.WebRequestTraceFilter
|    107 | doFilter              in org.springframework.web.filter.OncePerRequestFilter
|    192 | internalDoFilter . .  in org.apache.catalina.core.ApplicationFilterChain
|    165 | doFilter              in     ''
|     77 | doFilterInternal . .  in org.grails.web.servlet.mvc.GrailsWebRequestFilter
|    107 | doFilter              in org.springframework.web.filter.OncePerRequestFilter
|    192 | internalDoFilter . .  in org.apache.catalina.core.ApplicationFilterChain
|    165 | doFilter              in     ''
|     67 | doFilterInternal . .  in org.grails.web.filters.HiddenHttpMethodFilter
|    107 | doFilter              in org.springframework.web.filter.OncePerRequestFilter
|    192 | internalDoFilter . .  in org.apache.catalina.core.ApplicationFilterChain
|    165 | doFilter              in     ''
|    197 | doFilterInternal . .  in org.springframework.web.filter.CharacterEncodingFilter
|    107 | doFilter              in org.springframework.web.filter.OncePerRequestFilter
|    192 | internalDoFilter . .  in org.apache.catalina.core.ApplicationFilterChain
|    165 | doFilter              in     ''
|     96 | doFilterInternal . .  in org.springframework.web.filter.CorsFilter
|    107 | doFilter              in org.springframework.web.filter.OncePerRequestFilter
|    192 | internalDoFilter . .  in org.apache.catalina.core.ApplicationFilterChain
|    165 | doFilter              in     ''
|    107 | doFilterInternal . .  in org.springframework.boot.actuate.autoconfigure.MetricsFilter
|    192 | internalDoFilter      in org.apache.catalina.core.ApplicationFilterChain
|    165 | doFilter . . . . . .  in     ''
|    198 | invoke                in org.apache.catalina.core.StandardWrapperValve
|    108 | invoke . . . . . . .  in org.apache.catalina.core.StandardContextValve
|    472 | invoke                in org.apache.catalina.authenticator.AuthenticatorBase
|    140 | invoke . . . . . . .  in org.apache.catalina.core.StandardHostValve
|     79 | invoke                in org.apache.catalina.valves.ErrorReportValve
|     87 | invoke . . . . . . .  in org.apache.catalina.core.StandardEngineValve
|    349 | service               in org.apache.catalina.connector.CoyoteAdapter
|    784 | service . . . . . . . in org.apache.coyote.http11.Http11Processor
|     66 | process               in org.apache.coyote.AbstractProcessorLight
|    802 | process . . . . . . . in org.apache.coyote.AbstractProtocol$ConnectionHandler
|   1410 | doRun                 in org.apache.tomcat.util.net.NioEndpoint$SocketProcessor
|     49 | run . . . . . . . . . in org.apache.tomcat.util.net.SocketProcessorBase
|   1142 | runWorker             in java.util.concurrent.ThreadPoolExecutor
|    617 | run . . . . . . . . . in java.util.concurrent.ThreadPoolExecutor$Worker
|     61 | run                   in org.apache.tomcat.util.threads.TaskThread$WrappingRunnable
^    745 | run . . . . . . . . . in java.lang.Thread

Caused by GrailsTagException: [views/car/index.gsp:32] Attribute value quote wasn't closed (action="registration" controller="registration" params="[carId : ${car.id} ]").
->>   32 | populateMapWithAttributes in views/car/index.gsp
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

【问题讨论】:

    标签: grails


    【解决方案1】:

    默认情况下,一个 id 被分配给一个域类。因此,在 index.gsp 中,您可以简单地遍历汽车列表并为每辆汽车创建一个 Rent 按钮。您可以像下面这样使用 g:each 。

    <g:each var="car" in="${cars}"> // cars is a list of cars
      <p>Brand: ${car.brand}</p>
      <p>Model: ${car.model}</p>
      <p><button name="rentCar${car.id}" onclick="rentCar(this, ${car.id})">Rent Car</button</p>
    </g:each>
    

    希望这会有所帮助。

    另外,如果你想为每辆车的其他页面创建一个链接,你可以这样做

    <g:each var="car" in="${cars}"> // cars is a list of cars
      <p>Brand: ${car.brand}</p>
      <p>Model: ${car.model}</p>
      <p><g:link action="rent" controller="order" params="[car: ${car}, carId : ${car.id} ]">
        Rent Car
      </g:link></p>
    </g:each>
    

    g:link 标签将创建一个指向订单控制器的租用操作的链接。然后可以从参数那里访问汽车信息。


    新变化

    尝试以下更改。让我知道它们是否有效。

    1) 注册控制器

    def index(Integer max) {
    
            params.max = Math.min(max ?: 10, 100)
    
            Car car;
            if(params.carId){
                car = Car.get(params.carId) // fetch the car using the id passed in params
            }
    
            respond Registration.list(params), model:[registrationCount: Registration.count(), car: car]
        }
    

    在下面的显示操作中评论这些行

    def show(Registration registration) {
            respond registration
       //     println params
       //    Car b = Car.get(params.id)
        }
    

    2) 汽车/index.gsp

    <g:link action="index" controller="registration" params="[carId : ${car.id} ]">
    Rent Car
    </g:link>
    

    3) registration/index.gsp

    <div><p>Car ID : ${car.id} </p></div>
    

    【讨论】:

    • 谢谢你,我也想要这个;当用户单击按钮时,将打开一些页面,该页面将像订单表格一样,我不想在此页面中自动选择用户选择的汽车品牌和汽车型号。该怎么做?
    • @user3348410 我编辑了我之前的答案。看看吧。
    • 非常感谢,如果我要在我的订单视图中创建带有表单的订单域类和控制器,我会自动获取内容吗?或者我应该向订单控制器添加一些额外的参数?
    • 当我将您的代码添加到我的 cars/index.gsp 消息请求处理失败时,我收到此错误;嵌套异常是 java.lang.RuntimeException: Error initializing GroovyPageView Caused by [views/car/index.gsp:31] 属性值引用未关闭 (action="rent" controller="order" params="[car: $ {car}, carId : ${car.id} ]").
    猜你喜欢
    • 2014-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 2012-10-19
    相关资源
    最近更新 更多