I am having problems with the next/prev options not displaying on lists with a Groovy on Grails site. I have modified the automatically generated controller code to limit the items in the list to be items that were created by the user. This works fine, however, if the user has more than 10 items, the next/prev buttons don't show up as expected. Below are the relevant code snippits...
Controller:
def list = {
params.max = Math.min(params.max ? params.int('max') : 10, 100)
def login = authenticationService.getSessionUser().getLogin()
def authUser = AuthenticationUser.findByLogin(login)
def userAcct = User.findByLoginID(authUser)
def userServices = Service.createCriteria()
def results
if (userAcct.role == 'admin') {
results = userServices.list(params) {}
} else {
results = userServices.list(params) {
eq("userID", userAcct)
}
}
[serviceInstanceList: results, serviceInstanceTotal: results.count()]
}
GSP:
<div class="paginateButtons">
<g:paginate total="${serviceInstanceTotal}" />
</div>
When I log in with an account with the "admin' role, the next/prev links appear fine. Non-admin accounts do not display the next/prev links when there are more than 10 items to be listed. Can anyone see what I'm doing wrong?
Your criteria should give you a pagedResultList which has a totalCount. So try
to change the last line of your controller to:
[serviceInstanceList: results, serviceInstanceTotal: results.totalCount]
Related
This is my gsp view where I have to show the pagination but I am not getting any pagination and below that I've printed the job count and I am getting the correct job count.
<div class="paginate">
<g:paginate total="${total}" maxsteps="1" next="Forward" prev="Back" controller="job" action="viewJobs"/>
</div>
Job Count======${total} //Just for check
My controller code :
def viewJobs() {
User userEmail = springSecurityService.getCurrentUser()
List<Job> list1 = Job.findAllByCompany(userEmail.company,[max:5])
println "******list1*******" + list1
render(view: 'viewJob', model: [jobs: list1,total:list1.size()])
}
Your action should look like
def viewJobs(Integer offset) {
User userEmail = springSecurityService.getCurrentUser()
List<Job> list1 = Job.findAllByCompany(userEmail.company,[max:5,offset:offset])
println "******list1*******" + list1
render(view: 'viewJob', model: [jobs: list1,total:Job.countByCompany(userEmail.company)])
}
Pagination works with offset parameter (just like in SQL) and totalCount should be total number of records in DB not the size of the list(which will be always less than or equal to 5 in your case)
I am trying to alter the default index action for a Grails controller to enable some basic search criteria.
I have two main issues:
The paginate control at the bottom of the page forgets my search criteria.
How can I use the grails criteria createCriteria().list() operation with variable criteria. In particular, how should I account for things like null (ignored) criteria?
edit: I am adding my controller code:
def index(Integer max) {
session.alarmFilter = params.alarmFilter == null ? (session.alarmFilter == null ? [] : session.alarmFilter) : params.alarmFilter
params.max = Math.min(max ?: 10, 100)
def c = Alarm.createCriteria()
def results = c.list (params) {
if(session?.alarmFilter?.channelInterface != null) {
sqlRestriction("channel_interface_id = ${session.alarmFilter.channelInterface.id}")
}
}
respond results, model:[alarmFilter: session.alarmFilter, alarmInstanceCount: results.totalCount]
}
I'm not fond of saving the search criteria (alarmFilter) in the session since it doesn't really feel like session information. In particular, returning to this page will remember previous search criteria.
Also the if statement is causing an 'SQLException' when the criteria is not selected.
I am using following query to filter results in grails.
userList = SecUser.all.findAll{it.merchants.findAll {it.name.toLowerCase()=~ searchString.toLowerCase()}.size()>0}
In this code i have Users and each User have multiple merchants. I extract only that user whose merchant name matches a certain pattern.
Now i further have to filter these users on:
params.max
params.offset
So that i can perform pagination on them. Kindly please help me with this problem.
This has not been tested, but try something like this:
def query = SecUser.where {
merchants.any { merchant ->
merchant.name.equalsIgnoreCase( searchString )
}
}
def userList = query.findAll(max: params.max, offset: params.offset)
I'm trying to use the paginate tag in grails but it isn't working.
in controller:
def show(Integer max) {
params.max = Math.min(max ?: 10, 100)
def etpse
def total
if (params.data == 'all') {
etpse = Enterprise.findAll()
total = Enterprise.count()
}
else {
def paramsLike = "%" + params.data + "%"
etpse = Enterprise.findAllByKeywordLike(paramsLike)
total = Enterprise.countByKeywordLike(paramsLike)
}
[etpseList: etpse, instanceTotal: total]
}
in gsp:
<div id='pagination'>
<g:paginate total="${instanceTotal}" />
</div>
The paginate tag doesn't filter the results in your page, nor does it render the list of items. It merely creates links for the next/previous pages based on your request's parameters.
Your controller is responsible for fetching the correct page of data and your gsp is responsible for rendering the actual list of items.
The paginate tag parameters are designed to match the parameters to the GORM-injected list method and almost always go hand-in-hand:
class ItemController {
def list() {
[items: Item.list(params), itemCount: Item.count()]
}
}
view:
<g:each var="item" in="${items}">
<!-- render items here -->
</g:each>
<g:paginate controller="item" action="list" total="${itemCount}"/>
In the above code, the params list (including things like max and offset) is passed to the list method of the Item domain class, and this will grab a single page of data.
The paginate tag examines the request parameters for the same entries, determines which page of data you're viewing and creates the necessary links to the next and previous pages by using the correct values for max and offset.
Here you go.
def show(Integer max) {
Integer offset = params.int("offset")
Integer max = Math.min(params.int("max") ?: 10, 100)
if (params.data == 'all') {
params.data = '%';
}
def c = Enterprise.createCriteria()
def results = c.list(max: max, offset: offset) {
ilike('keyword', "%" + params.data + "%")
}
[etpseList: results, instanceTotal: results.totalCount]
}
You have to pass your params max and offset into your findAll, otherwise Grails does not know how to paginate your resultset.
For example,
Book.findAll(query, [max: 10, offset: 5])
The ability to use Pagination is the goal, however I'm not sure how to work with this. The relationship is unidirectional hasMany (seen below). As current it works fine without pagination (see Screenshot), but to work with pagination I have to change the controller to use createCriteria. This is where I come into difficulty as its quite strange for the relationship.
Domain
Class Tag {
String Tag
User user
static hasMany = [events: Event]
}
Controller
def searchTags() {
println("TAG CONTROLLER - Params sent on click of tag are: "+params.selected)
def results = Tag.findByTagAndUser(params.selected, lookupPerson())
//resultTotal is for show for the time being
[query: params.selected, results: results, resultTotal: 0]
}
GSP
<g:each in="${results.events}" status="i" var="t">
.... ommited as unnessary
</g:each>
//Not working yet due to confusing createCriteria issue
<div class="pagination">
<g:paginate total="${resultTotal}" />
</div>
I could do with a little guidance, this is what I'm thinking so far but I'm a little confused:
def tagCriteria = Tag.createCriteria()
def result = tagCriteria.list (max: 50, offset: 10) {
eq("tag", params.selected)
and {
eq("user", lookupPerson())
}
//Not sure what to do at this point compared with the findByTagAndUser(params.selected, lookupPerson()).events events being the hasMany relationship seen in domain
events {
}
}
Give this a try.
def searchTags() {
def tagCriteria = Tag.createCriteria()
def results = tagCriteria.list (max: 50, offset: 10) {
eq("tag", params.selected)
eq("user", lookupPerson())
projections {
property("events")
}
}
[query: params.selected, results: results, resultTotal: results.totalCount]
}
HQL version - The problem is you have to do the same query twice, but select the count(e)
Tag.executeQuery("""
Select e
from Tag t join t.events as e
where t.tag = :selected
and t.user = :user
""", [selected: params.selected, user: lookupPerson()], [max: 50, offset 10])