Referencing <tmpl:myTemplate /> in grails taglib - grails

I've created a tmpl gsp tag containing a bit of markup that's used throughout the forms in my webapp (/shared/formRow.gsp). I'd like to reference this tmpl gsp tag in a groovy taglib I've created. Is this possible?
Here's the def from my taglib...
def checkboxRow = { attrs ->
def name = attrs.name
def value = attrs.value
def label = attrs.label
def defaultLabel = attrs.defaultLabel
out << "<tmpl:/shared/formRow name='${name}' label='${label}' defaultLabel='${defaultLabel}'>"
out << " ${checkBox(id: name, name: name, value: value)}"
out << "</tmpl:/shared/formRow>"
}
I realise the syntax is a bit different in taglibs (e.g. you need to do ${checkBox(...)} rather than ), but is it possible to reference your own tmpl gsp tag in a similar way? If so, what syntax would I use?

Well, it turns out that it's in the Grails documentation, here.
You should just call the render template method like this:
def formatBook = { attrs, body ->
out << render(template: "bookTemplate", model: [book: attrs.book])
}
Simple really!

Related

Why does overriding putAt result in MissingPropertyException?

I've been trying to take advantage of operator overloading in Groovy by defining a custom putAt method in my POGO like this:
class Book {
Map additionalInfo = [:]
def putAt(key, value) {
additionalInfo[key] = value
}
}
So that I can do something like, book['notes'] = 'I like this one.' (let's say this makes sense). However, I've been getting:
groovy.lang.MissingPropertyException: No such property: notes for class: Book
at BookSpec.Set property using putAt(BookSpec.groovy:40)
My class is part of a Grails application so I'm not sure if Grails has something to do with the problem. Can anyone enlighten me on this?
The signature should be
def putAt(String key, value)
Instead of doing putAt and then override the operator, there is an easy/better way by adding the propertyMissing methods.
Here is the link for more explanation.
class Foo {
def storage = [:]
def propertyMissing(String name, value) { storage[name] = value }
def propertyMissing(String name) { storage[name] }
}
def f = new Foo()
f.foo = "bar"
assertEquals "bar", f.foo

Grails Mapping Template

i want to make grails mapping template.
the example like this.
URL :
http://localhost:8080/controller/action/id/
i have 2 gsp views
1.Product
2.Product_create
when variable id == "create"
grails automatically display product_create if not grails will display product.
is anyone can solve this??
please correct my english. thankyou.
Something like:
def product( String id ){
if( 'create' == id ) return render( view:'product_create' )
def product = doSomethingWithId()
[ product:product, ... ] // here the default "product.gsp" will be rendered
}

Grails/Groovy isn't persisting change in object's collection

I have the following problem:
My object route contains a list of routepoints. When I alter this list, the changed list is saved. But when the next method accesses the list, it seems like the change reverted. I ruled some kind of transaction rollback out, b/c on the end of the altering method, i acces the list by loading it from the database and it still has the right (altered) size. Here's the code:
First the altering method:
def removeStationFromRoute(station){
def driver = Driver.get(Integer.valueOf(requestAccessService.getParams().userId))
def route = driver.routes.find{
it.routeDate == new Date().clearTime()
}
def rp = Routepoint.findByStation(station)
route.routepoints.remove(rp)
def newRoute = driver.routes.find{ it.routeDate == new Date().clearTime()}
println 'new route size: ' + newRoute.routepoints.size()
def newRoute2 = Route.get(route.id)
println 'new route from db size: ' + newRoute2.routepoints.size()
}
Both prints return a size of 5, which is correct. Right after this method is carried out, this method is executed:
def getDriverRoute(){
def driver = User.get(Long.valueOf(params.userId))
def route = driver.routes.find{ it.routeDate == new Date().clearTime()}
println 'serialized route size: ' + route.routepoints.size()
def routeString = jobService.serializeRoute(route)
log.info('Route with ' + route.routepoints.size() + " stations serialized for User " + driver.encodeAsHTML())
render routeString
}
Which prints a size of 6, as if no change happened to the list. I already tried saving the driver, the route and the routepoint after the change is made in the "removeStationFromRoute"-List, as well as checking the three objects for errors. Didn't help.
Thanks for any ideas what to do!
I guess you have a 1-N relationship between Route and Routepoints? Something like
class Route {
static hasMany = [routepoints: Routepoint]
}
class Routepoint {
static belongsTo = [route: Route]
}
You should not add/remove routpoints using the add/remove methods of the Collection interface. Instead you should use the addTo*/removeFrom* GORM methods, e.g.
route.addToRoutepoints(routepoint)
route.removeFromRoutepoints(routepoint)
Firstly,
After you have used route.removeFromRoutepoints(routepoint)
to remove the mapping of the Routepoint with Route in the first method, the Route Object Still needs to be persisted using .save/.merge method.(Check here )
Secondly.
In hibernate, using Domain.get(id) will not always hit the Database, IF the object already cached in the Hibernate session. Check here
Hope it helps...

Dynamic namedQueries

Is their a dynamic namedquery on grails? Im not sure if its the right term but, I mean a namedquery that can be true to all.
Something like:
namedQueries = {
dynamicQuery{ term, name, value ->
term(name, value)
}
}
Then it can be called maybe like but not exactly:
def testClass = TestClass.dynamicQuery('eq', 'lastname', 'Bill').list()
and so you call it too like:
def testClass = TestClass.dynamicQuery('gt', 'id', 12).list()
This one might not work but is their something similar in grails?
UPDATE
The idea is that so I can chained it as many as I want like:
def testClass = TestClass.dynamicQuery('gt', 'id', 12).dynamicQuery('eq', 'stat', 11).list()
This is so that I dont have to create many namedqueries. I was hoping I can create one and use it multiple times.
Grails' createCriteria method generates Grails HibernateCriteriaBuilder instance, within which you can call invokeMethod method to dynamically create query criteria, which usually is defined by the standard DSL.
Here is a example in some controller:
private String dynamicCriteriaTest(String term, name, value) {
def c = TestClass.createCriteria()
def param = []
param << name
param << value
def result = c.list{
c.invokeMethod(term, param as Object[])
}
return result.toString()
}
def test() {
render dynamicCriteriaTest('eq','lastname','Bill')
}
That will get something you want.
update
If you want to call this method multiple times, pass the criteria parameters in an a List then execute the query:
private List dynamicCriteriaTest(List param) {
def c = TestClass.createCriteria()
def paramList = param.collate(3) //split the parameters into groups
def result = c.list{
paramList.each { paramInstance ->
def command = paramInstance[0]
paramInstance.remove(0)
c.invokeMethod(command, paramInstance as Object[])
}
}
return result
}
def test() {
ArrayList param = new ArrayList()
//the 1st criteria
param << 'gt'
param << 'id'
param << (long)12 //you have to check the Grails [HibernateCriteriaBuilder] API to make sure the parameter passed to `invokeMethod` is in the right type (e.g. **long** in this case)
//the 2nd one
param << 'eq'
param << 'stat'
param << (long)11
//even more
param << 'like'
param << 'description'
param << 'some text%'
render dynamicCriteriaTest(param)
}
In Grails you have NamedQueries and also Where Queries. The example you give can possibly be implemented by using a namedqueries and placing this in a abstract domain class. Your domain classes should extend this abstract domain.

Importing and using groovy code in GSP

I am trying to use a groovy function inside a GSP. Please help as I am about to tare my hair out here.
At the top of my GSP i have <%# page import = company.ConstantsFile %>
Inside my GSP I have
<p>
I have been in the heating and cooling business for <%(ConstantsFile.daysBetween())%>
</p>
and my ConstantsFile.groovy
package company
import static java.util.Calendar.*
class ConstantsFile {
def daysBetween() {
def startDate = Calendar.instance
def m = [:]
m[YEAR] = 2004
m[MONTH] = "JUNE"
m[DATE] = 26
startDate.set(m)
def today = Calendar.instance
render today - startDate
}
}
I have also tried changing renter to puts, system.out, etc but that isn't my main problem.
Error 500: Internal Server Error
URI
/company/
Class
java.lang.NullPointerException
Message
Cannot invoke method daysBetween() on null object
So I try
<p>
I have been in the heating and cooling business for <%(new ConstantsFile.daysBetween())%>
</p>
but then i get
Class: org.codehaus.groovy.control.MultipleCompilationErrorsException
unable to resolve class ConstantsFile.daysBetween # line 37, column 1. (new ConstantsFile.daysBetween()) ^ 1 error
Please someone help me or point me to a website that shows what to do.. I have tried googling and everything talks about a g:select or some other kind of tag... I just want to output the result of the function like I used to in the JSPs.
First, your GSP's import should be:
<%# page import="company.ConstantsFile" %>
Second, your daysBetween should be static (it makes more sense) and you don't render from anything but a controller:
class ConstantsFile {
static daysBetween() {
def startDate = Calendar.instance
def m = [:]
m[YEAR] = 2004
m[MONTH] = "JUNE"
m[DATE] = 26
startDate.set(m)
def today = Calendar.instance
return today - startDate
}
}
Third, access it in the following way:
<p>I have been in the heating and cooling business for ${ConstantsFile.daysBetween}</p>
And lastly, you should use a taglib for this. I'm editing my post now to add an example
class MyTagLib {
static namespace = "my"
def daysBetween = { attr ->
out << ConstantsFile.daysBetween()
}
}
Then use in your GSP
<p>I have been in the heating and cooling business for <my:daysBetween /></p>

Resources