From the Grails controller function if i want to retrieve a value from another object, i retrieve it as follows:
def person = Person.get(10)
println person.name
The above code will return a person object where the ID is 10, and also it will return the name of that particular user.
Likewise, how can i do such a computation in the view.
View
<body>
<table>
<g:each in="${personInstanceList}" status="i" var="personInstance">
<tr class="${(i % 2) == 0 ? 'even' : 'odd'}">
<td><g:link action="classesoffered"
url="${fieldValue(bean: personInstance, field: "id")}"
id="${personInstance.id}" >
${personInstance.id}
</g:link></td>
.....
... </body>
The above code will display the ID of the person Object. Is it possible for me to use this ID to retrieve a value of another object. For example.
def school = School.get(${personInstance.id})
Can i use the ID (${personInstance.id}) in order to retrieve the school from the View ?
Note: Hope i have explained the question properly. In a nutshell I want to do a computation at the view. To retrieve schoolinstance from ${personInstance.id} from the view.
UPDATE
Person MODEL
String name
int school
School MODEL
String nameOfSchool
You can import a domain in your view with: (first line of the gsp)
<%# page import="com.yourPackage.School" %>
And then, you can use the tag set to create a new variable inside you view.
For example:
<g:set var="school" value="${ School.get(personInstance.id) }" />
If you want to print the value in your GSP (for example the name of the school), you can use:
${ school.nameOfSchool }
(if school is not null of course)
Hope that helps
Rather than trying to do this kind of thing within the view, you should redesign your domain model to fit the task. If you want each Person to be linked to their School then you should do it with a proper association rather than storing an ID (for which, incidentally, you're using the wrong type - by default the ID of a Grails domain class is a Long, not an int):
class Person {
String name
School school
}
class School {
String name
}
and create instances like this:
// create a new school
def school = new School(name:'Example school')
// or fetch an existing one from the DB
// def school = School.get(1)
def person = new Person(name:'Illep', school:school)
With this model, the GSP can access the school name simply as
${personInstance.school?.name}
Related
I want to display all games under a certain category in pagination (10/page)
This is my controller
def listGame(){
def category = GameCategory.list()
def platform = Platform.list()
def currentCategory = params.categoryName
def myCategory=GameCategory.findByCategoryName(currentCategory)
def games = myCategory.games
[currentCategory:currentCategory, category:category, games:games, platforms:platform, gameCount:Game.count(), chosenPlatform:params.platform]
}
and this is my pagination code in my view
<g:each in="${games}" status="i" var="game">
${game.gameTitle}
</g:each>
<div class="pagination">
<g:paginate action="listGame" total="${gameCount}" />
</div>
When I have 9 games in the current category the page 12 showed up wherein it shouldn't
When I have 11 games in the current category all 11 games are displayed in page 1 and clicking page 2 will result in this error
There are a couple of things to address.
Make sure categoryName is not coming into the controller as null.
Make use of the max and offset parameters that the paginator is providing to select the appropriate Games.
The category name
Because the paginator is creating the URL that calls into the controller, and your controller needs the category name, the paginator must add the category name to the params it calls the controller action with. You can achieve this with the tag's params attribute:
<g:paginate action="listGame" total="${gameCount}" params="${[categoryName: currentCategory]}"/>
Max & offset
The controller needs to use max and offset parameters to know what subset of the Games to retrieve from the database and render in the view. However, in some cases, such as when visiting the URL http://blah/someController/listGame, there would be no max and offset params. This is something your controller action must be able to handle. It goes something like this:
def max = params.max ?: 10
def offset = params.offset ?: 0
So the max and offset params will be used if they are available. Otherwise they'll use default values.
Finally, you need to use these parameters to select the Games. For that you can use a where query:
def games = Game.where {
categories.categoryName == currentCategory
}.list(max: max, offset: offset)
Something interesting about the returned games object: It acts like a list, but it's actually a grails.gorm.PagedResultList. That's a good thing because it contains the total number of records in the result (ignoring max and offset). In other words, it's your new gameCount.
You can read more about where queries in the Grails documentation. I also have a series of articles which cover where, criteria and HQL queries in more detail.
Putting it all together, listGame() would look like this:
def listGame(){
def category = GameCategory.list()
def platform = Platform.list()
def currentCategory = params.categoryName
def max = params.max ?: 10
def offset = params.offset ?: 0
def games = Game.where {
categories.categoryName == currentCategory
}.list(max: max, offset: offset)
[currentCategory:currentCategory, category:category, games:games, platforms:platform, gameCount:games.totalCount, chosenPlatform:params.platform]
}
Looks like you haven't done your homework. Please go through grails doc and other tutorials, to understand how pagination works.
Just to give you a hint. You are doing two things wrong here.
You are not getting a paginated list at the first place from controller
You are not sending back all the required data back to the controller, from the pagination link. And that's the reason you are getting the error!
I have two domains that are connected with one-to-many relation - One User may have many Associations. I want to view all associations that belong to this user. I'm using scaffolding plugin. So code that should return list of Associations in AssociationController looks lile this:
def index(Integer max) {
respond Association.list(params), model:[associationInstanceCount: Association.count()]
}
And on the User view page I have the following code:
<g:form controller="Association" >
<fieldset class="buttons">
<g:hiddenField name="user.id" id="user.id" value="${userInstance.id}"/>
<g:actionSubmit class="list" action="index" value="${message(code: 'default.list.label', default: 'Show Associations')}"/>
</fieldset>
</g:form>
When I press this actionSubmit user.id is sent with the request and it is within params map (I checked it with debug) but for some reason Association.list(params) returns all Associations (for all users) despite the fact that I'm using this user.id within params. A also tried rename user.id to just user and it didn't work either. Seems like this .list() should be used only for sorting or I'm doing something wrong. Can you help me with this please? Thank you!
To clarify the given answer: list( params ) returns ALL results for the domain object, and accepts only sorting (order by) and view-port (limit/offset) parameters. It does not provide any where clause (well, apart from discriminator-column)
UPDATE:
you can use findAllBy*:
Association.findAllByUserId( params.long( 'user.id' ), params )
or criteria if you need to make your query more complex:
Association.withCriteria{
eq 'id', params.long( 'user.id' )
maxResults params.int( 'max' ) ?: 10
firstResult params.int( 'offset' ) ?: 0
if( params.sort && params.order ) order params.sort, params.order
}
According to Grails documentation, list does not take an id as parameter.
Seeing your max, it would be Association.list(max: max) and for what you want, it is something like:
Association.findAllByUserId(params.id, [max: max])
Where params.id contains the id of the wanted user (or params['user.id']).
More on findAllBy...
Not sure about the previous response but :
Association.where {
user {
eq 'id', params['user.id']
}
} .list()
You can add params to list call if you use pagination.
Another solution :
def index(User user) {
respond user.associations, , model:[associationInstanceCount: user.associations.size()]
}
But you'll have to name your param 'id'
It mostly depends on how you have designed your domain objects and what's your goal here.
I created a taglib to shorten input field code. It presets 'name', 'value' and others. Now I need to get a bean value, but the field holding that value is dynamic.
See some code (shortened to better work out my problem):
gsp:
<g:validatedInputField bean="${command}" field="surname" />
<g:validatedInputField bean="${command}" field="name" />
taglib
def validatedInputField = { attrs, body ->
def field = attrs.field
def bean = attrs.bean
if (field && bean) {
def val = bean.field
out << "<input type=\"text\" name=\"$field\" bean=\"$bean\" value=\"$val\">"
}
}
So the problem is the following line. It does obviously not work because there is no field 'field' in the bean. I want it to be dynamically replaced by 'name' or 'surname' or whatever the value of the param 'field' is.
def val = bean.field
I tried exprimenting with various GString/interpolation variations, but nothing worked.
Of course I could just add another param to pass the value, but I feel like it shouldn't be required as I already have everything I need to get it in the taglib...
Can you please give me some directions?
Thanks
In groovy, you can refer to a member of an object dynamically by using GStrings. For example:
def val = bean."${field}"
You could even perform some logic inside the GString. Let's say you have a default field and you want to use the name inside the 'field' variable only if it is not null:
def val = bean."${field ? field : "default"}
If bean is an object instance and field is a String that represent a member of that object, you can try something like:
def val = bean."$field"
I have a domain class called Application as follows:
class Application {
static hasOne = [resumption:Resumption, employee:Employee]
//Employee employee
Date startDate
Date endDate
Integer amountOfDays
String leaveRecommended
String leaveNotRecommended
Date supervisorDate
String toString(){
return "Application for ${employee.lastName}, ${employee.firstName}"
}
}
In the ApplicationController I'm trying to write a query that is going to find all applications that match a particular employee id. I do so as follows:
def applicationlist(){
if(!params.max){
params.max = 10
}
def query
def criteria = Application.createCriteria()
def results
query = { eq("employee_id", Long.parseLong("1")) }
results = criteria.list(params, query)
render(view:"employeeapplicationlist", model:[applicationlist:results])
}
Now I keep getting the error: "could not resolve property: employee_id"
I've checked the generated Application table in MySql, there is a column called employee_id with a value. The weird thing is I can access any other property (like amountOfDays), so what's the deal with employee_id? Why is it complaining that it cannot resolve the property? What am I missing? Thanks in advance.
Associations in the criteria DSL are of the form
Application.withCriteria{
employee{
eq 'id', 1
}
}
http://grails.org/doc/latest/guide/GORM.html#criteria
But you could probably just do:
def employee = Employee.proxy(1)
Application.findAllByEmployee( employee )
This appears a few times in the Grails User Guide as 'querying associations'
Oh well it looks like I'm still not fully adjusted to interfacing with the database on an Object level. For anyone else with this or a similar problem, here's the fix:
query = { eq("employee.id", Long.parseLong("1")) }
Sine the Application Domain class has one Employee, then we just need to access the id field of that employee. Remember we're in the ApplicationController.
I want to create a report for my domain class instances but not all, just the ones user selected in the GSP table (selecting checkboxes). On my report I will also have some logic - few conditionals, some calculations etc. I would also have to get some additional data from database. How do I do this? Should I get values of selected checkboxes in cotroller and pass it to jasper cotroller? Something like this:
GSP:
<g:each in="${books}" var="bookInstance">
<td> <g:checkBox name="book_${bookInstance.id}"/> </td>
</g:each>
Action:
def bookReport = {
def bookList = []
params.each {
if(it.key.startsWith("book_")){
bookList.add((it.key - "book_") as Long)
}
}
def bookCriteria = Book.createCriteria()
def books = bookCriteria.list {
'in'('id',bookList)
}
chain(controller:'jasper', data:books, action:'index', params:params)
}
I used iReport for report creation. I've tried creating report without SQL query and parameters. My logic was that if I pass a map of domain instances to jasper controller as I did in the example above I dont need to specify data source in report. But I get an empty report.
I also tried seting the report datasource to my database and report query to this: select * from book where $X{IN,id,books}. In that case, no matter what I select report is created for all book instances.
Have you tried...
chain(controller:'jasper', model:[data:books], action:'index', params:params)
...while leaving the SQL string empty in your .jrxml?