Previously I blogged about implementing a filter feature and ability to show/hide columns in the grid Here. We are going to make another small enhancement to it, we will allow the User to select how many records to display per page (from a pre-defined list). We will also use some powerful Yahoo User Interface (YUI) Do functions to implement this.


Demo Currently Unavailable

So, the first thing to do is build the area where the user selects how many records to display per page, with 5 being the default.

view plain print about
1Records Per Page:
2<a id="p2" class="" href="javascript:changePage(2)">2</a> |
3<a id="p4" class="" href="javascript:changePage(4)">4</a> |
4<a id="p5" class="selected" href="javascript:changePage(5)">5</a> |
5<a id="p6" class="" href="javascript:changePage(6)">6</a> |

I implemented a selected class to show which of the options is currently selected by the user. It just bolds the text. When the user clicks on the link, it calls the changePage function. When the user clicks on one of the numbers, the following things need to happen:

  1. Strip current selection of its selected class so it goes back to normal text
  2. New selection should get the selected class so it gets bolded
  3. Change the grid pageSize
  4. Reconfigure the grid to reflect the new pagesize

view plain print about
1function changePage(newSize)
2{
3    //Get current link anchors with selected class
4    var currClasses = YAHOO.util.Dom.getElementsByClassName('selected', 'a');
5    //Remove selected class from them
6    YAHOO.util.Dom.removeClass(currClasses,'selected');
7    //Specify the selected link anchor to have selected class
8    YAHOO.util.Dom.addClass('p' + newSize,'selected');
9    //Store new value in hidden form variable
10    document.getElementById('pages').value = newSize;
11            
12    //Get grid footer
13    gridFoot = grid.getView().getFooterPanel(true);
14    //Reload the data using new size
15    grid.getDataSource().reload({params:{start:0,limit:newSize}});
16    //Redo the paging toolbar with the new size
17    var paging = new Ext.PagingToolbar(gridFoot,grid.getDataSource(),{
18            pageSize:newSize
19        }
20    );
21            
22    //Reconfigure the grid to have the changes take effect
23    grid.reconfigure(grid.getDataSource(),cols);
24}

So, when the user clicks on a number, we use the YUI Dom's getElementsByClassName to get current anchor links with "selected" class. We then remove this clasee from that anchor link. We also get the new anchor link that was selected and add the "selected" class to it. We also have a hidden form variable called pages, where we store the new pagesize selected by the user (this will be used later on). Finally, CF8 uses the YUI Grid implementation, so looking into that, we first get the grid Footer. We also reload the Grid datastore pasing in a limit of the newly selected pagesize. This reloads the data with the new size but we also have to change the paging toolbar to reflect the new size, which is done next. In the end, we reconfigure the grid to reflect the changes.

Now, as such the code till now would implement user selected pagesizes. But the problem comes in when the user selection interacts with our grid filter. Since, we specified a pagesize of 5 when building the cfgrid, if the user uses the filter options ColdFusion loads the grid again with the pagesize of 5. To stop this, we modify the cfgrid code and the CFC a little bit.

view plain print about
1<cfgrid name="usersgrid" pagesize="5" format="html" width="100%" height="200"
2 bind="cfc:UsersB.getUsers({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection},getPageSize(),{filtercolumn},{filter})">

3                                
4<cfgridcolumn name="FirstName" header="First Name">
5<cfgridcolumn name="LastName" header="Last Name">
6<cfgridcolumn name="UserName" header="User Name">
7<cfgridcolumn name="DisplayName" header="Display Name">
8<cfgridcolumn name="UserAccountingCode" header="GL Code (User)" display="false">
9<cfgridcolumn name="Phone" header="Phone No." display="false">
10                                                    
11</cfgrid>

To the cfgrid we added a new parameter to be passed in to the CFC, this parameter gets the pagesize from a hidden form variable (which we change in the changePage function) using the getPageSize() function.

view plain print about
1function getPageSize()
2{
3    //Return the pagesize from the form variable
4    return document.getElementById('pages').value;
5}

Next, we modified our CFC function to handle this change.

view plain print about
1<cffunction name="getUsers" access="remote" returntype="any">
2        <cfargument name="page" required="yes">
3     <cfargument name="pageSize" required="yes">
4     <cfargument name="gridsortcolumn" required="yes">
5     <cfargument name="gridsortdirection" required="yes">
6     <cfargument name="customPageSize" required="no" default="0">
7     <cfargument name="filtercolumn" required="no" default="">
8     <cfargument name="filter" required="no" default="">
9    
10     <!--- If a custompagesize was passed in and it is greater than 0, use that otherwise use the default
11     page size specified in cfgrid tag --->

12     <cfif Val(Arguments.customPageSize) GT 0>
13            <cfset pageSizeToUse = Arguments.customPageSize>
14        <cfelse>
15            <cfset pageSizeToUse = Arguments.pageSize>
16        </cfif>
17    
18     <cfquery name="selUsers" datasource="RIADemo">
19            SELECT
20                FirstName, LastName, DisplayName, UserName, UserAccountingCode, Phone
21            FROM
22                Users
23            <cfif Arguments.filtercolumn NEQ "" AND Arguments.filter NEQ "">
24                WHERE #Arguments.filtercolumn# LIKE '#Arguments.filter#%'
25            </cfif>
26            
27            <cfif Arguments.gridsortcolumn NEQ "">
28                ORDER BY #Arguments.gridsortcolumn# #Arguments.gridsortdirection#
29            </cfif>
30        </cfquery>
31        
32        <cfreturn queryconvertforgrid(selUsers,Arguments.page,pageSizeToUse)/>
33    
34    </cffunction>

In the CFC, we added a new paramter called customPageSize, defaulted to 0 if it is not passed in. Then we check if the value of that parameter is greater than 0. If it is, we use that parameter as our pageSize otherwise we use the default specified in the cfgrid tag. Next we had to change the queryconverforgrid() call to use the pageSizeToUse variable.

What this does is, when the user selects a custom pagesize, the hidden form variable is changed to reflect this. So, when the grid is refreshed by ColdFusion, we pass in this hidden form value and use it as the pagesize instead of using the default specified.