Reputation: 2833
i'm trying to create some app with this logic;
I have the entries with cars, i want to add (rent) button to each entry at list of my cars, when will click to button someone, button will open some form for entry contact informations and this form should get car id number automatically
here is my domain class with cars. I don't understand how to add the button to my index.gsp where listed my entries about cars and how get the id number of selected car from list and send to the form
How to do this? how is working this logic?
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"])
}
}
Here is what i tried;
Here is my Car/index.gsp in view files. - here i get car id's and tried to put button to each id. I want to do this; button will go to another page where will be registration page for rent this car, and in this registration page user will see the id number of the car which one selected.
<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>
And here is domain-class of my Registration Class
package rentme
class Registration {
String yourName
static constraints = {
yourName()
}
}
And here is my Registration Controller , i created it with generate-all command
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 }
}
}
}
I added to there in def show() method this lines of code for get car.id
def show(Registration registration) {
respond registration
println params
Car b = Car.get(params.id)
}
and here is my registration page in views 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…"/></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>
i added to this code here for get 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Upvotes: 0
Views: 885
Reputation: 1162
By default, an id is assigned to a domain class. So, in the index.gsp you can simple iterate over the list of cars and create a Rent button for each one of them. You can use g:each for that like below.
<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>
Hope this helps.
Also, if you want a link created for some other page per car, you can do
<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>
The g:link tag will create a link to the order controller's rent action. The car information can then be accessed there from the params.
New changes
Try the changes below. Let me know if they work.
1) Registration Controller
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]
}
Comment these lines in the show action like below
def show(Registration registration) {
respond registration
// println params
// Car b = Car.get(params.id)
}
2) Car/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>
Upvotes: 1