Breaking down your query results into pages (Paging Tutorial) Part-II
This is an extension to my last tutorial "Breaking down your query results into pages (Paging Tutorial)" which is posted here on www.easycfm.com
In the last tutorial, you could retrieve a dataset with a <cfquery>, then use a technique to seperate the results over several pages. It simply ;
- took the total "recordCount"
- divided that with the "number of records per page"
- then displayed the number of pages at the bottom of the table.
It was lacking in some basics, like what would you do if you had 25 records and wanted to display 3 per page. You would then have to modify the script with some kind of a rounding function (rnd() or ceil()). It also used <cfloop> instead of using <cfoutput query="" maxrows="" startrow="">. It was a basic tutorial.

I have tried something a little more sophisticated here. I needed paging in almost every part of my application, so I created a custom tag. I would like to share that information, perhaps you may find it useful....

Just follow along...

----------------------------------------------------------------------------------------------------
Create two files 1. paging.cfm and 2. paging_tester.cfm (or whatever.cfm)
----------------------------------------------------------------------------------------------------
PAGING.CFM
----------------------------------------------------------------------------------------------------

<!--- The following attributes are needed. If you see a value for "default=", then that is an option part of our tag --->

<cfparam name="attributes.QueryName" default="">
<!--- REQUIRED : Name of the query that is used in the calling page--->

<cfparam name="attributes.SelectedColumns" default="">
<!--- REQUIRED : List of columns to be shown --->
<!--- if column list is not given, or cfquery.columnlist is used, then the columns will appear, ordered by their names --->

<cfparam name="attributes.ShowRowCount" type="boolean" default="false">
<!--- OPTIONAL : Shows row number in the first column --->

<cfparam name="attributes.ReplaceChar" default="_">
<cfparam name=
"attributes.ReplaceWith" default=" ">
<!--- OPTIONAL : Column Names are like "emp_name" then the underscore can be replaced with a "space" --->

<cfparam name="attributes.ShowDiagnostics" type="boolean" default="false">
<!--- OPTIONAL : Diagnostic information at the end of query --->

<cfparam name="attributes.RecordsPerPage" default="25">
<!--- OPTIONAL : This is used for paging --->

<!--- BEGIN GENERAL SETUP : ----------------------------------------------- --->
Lets try to forsee everything we might need during the processing of this custom tag ...
--->

<!---
This is used at the end, while showing the diagnostics row. cfquery provides 4 diagnostic variables like recordcount, currentrow, executiontime and columnlist.
- If we want to display the diagnostic information, (see <cfparam> tag above) we will do so in the same table as the query result.
- If we want to display the query_name.currentrow (i.e. serial number of the rows), we need to add that column so we can format the table correctly.
Thats exactly what the following does...
--->

<cfif attributes.ShowRowCount>
    <cfset diagColumnWidth = ListLen(attributes.SelectedColumns)+1>
<cfelse>
    <cfset diagColumnWidth = ListLen(attributes.SelectedColumns)>
</cfif>

<!---
Set up the variables so that we can evaluate them later, if they ask...
--->

<cfset ExecutionTime = "caller.cfquery.ExecutionTime">
<cfset RecordsReturned = "caller.#attributes.QueryName#.recordcount">

<!---
Since we want "page numbers" and "next" & "previous" links at the bottom of the table, lets setup some variables for that
--->

<cfif attributes.RecordsPerPage neq "">
    <!--- START Setup Paging --->
        <cfset TotalRecords = evaluate(RecordsReturned)>
        <cfset TotalPages = Ceiling(TotalRecords/attributes.RecordsPerPage)>
        <cfparam name=
"URL.ThisPage" default="0">
        <cfset StartRow = (URL.ThisPage*attributes.RecordsPerPage)+1>
        <cfset NextPage = URL.ThisPage+1>
        <cfset PreviousPage = URL.ThisPage-1>

    <!--- END setup for paging --->
</cfif>

<!--- END GENERAL SETUP : ----------------------------------------------- --->

<!--- Tag Start: --->

<!---
When a custom tag has an end tag, coldfusion calls it twice. Once when <cf_custom_tag ...> is encountered/opened and second when </cf_custom_tag> is encountered/closed. We should be able to use this to our advantage...
If you ask for the variable value of "thisTag.ExecutionMode" it will give you either "Start" or "End". This is how we know when the custom tag started processing and when it ended.
--->

<cfif ThisTag.ExecutionMode eq 'Start'>

<!--- check to see if user provided an end tag --->
<cfif not ThisTag.HasEndTag>
    <!--- Show message on error --->
    <h3>An error occurred ...</h3>
    <pre>
        The cf_paging tag requires an end tag. Please make sure that it exists and try again.
        The tag processing aborted...
    </pre>
    <cfexit method="exittag">
    <!--- If no end tags are found "exit" tag processing --->
</cfif>

<!--- if end tag was found, start processing table for query output --->

<table>
    <tr bgcolor="beige">

    <!---
        check if the user wants serial number as the first column. Remember we setup all this information before hand.
    --->

    <cfif attributes.ShowRowCount>
        <th>Record Count</th>
        </cfif>

    <!--- Now lets render the column headers from the query --->
    <cfloop index="ColHeaders" list="#attributes.SelectedColumns#">
        <cfoutput>
            <th>#ReReplace(ColHeaders, attributes.ReplaceChar, attributes.ReplaceWith, "All")#</th>
        </cfoutput>
    </cfloop>

    </tr>
    <!--- // ------------------------------------------------------------------------ // --->
    <!--- start populating the table values --->

    <!--- You can use the "caller" scope, so you can call/reference the set variables in the calling template --->
    <cfoutput query="caller.#attributes.QueryName#" maxrows="#attributes.RecordsPerPage#" startrow="#StartRow#">
    <tr>
        <!--- check to see if user wants serial number column. if "yes" use current row attribute of cfquery --->
        <cfif attributes.ShowRowCount>
            <cfset getRecordCount = "caller.#attributes.QueryName#.currentrow">

            <!--- Again, we set this up before --->
            <td>#evaluate(getRecordCount)#</td>
        </cfif>
        <!--- Render the query output here --->
        <cfloop index="ColValue" list="#attributes.SelectedColumns#">
            <td>#evaluate(ColValue)#</td>
        </cfloop>
        </tr>
    </cfoutput>
    <!--- // ------------------------------------------------------------------------ // --->

    <!--- This is the first part of our tag. Now we want to do stuff at the end. Like showing diagnostics, showing page navigation menu... Execute this part when the     custom tag is called again. The following <cfelse> tag is really saying, <cfif thisTag.ExecutionMode eq "end"> as we discussed above
    --->

<cfelse>

    <!--- BEGIN DIAGNOSTIC SETUP: ----------------------------------------------------------------- --->
    <!--- if user wants to see diagnostics, show the following below --->

    <cfif attributes.ShowDiagnostics>
        <tr>
            <td bgcolor="#CCCCCC" colspan="
<cfoutput>#diagColumnWidth#</cfoutput>">
            <cfoutput>

            <div style="font-family:monospace;font-size:8pt;text-align:left;">
                Query Execution Time: #evaluate(ExecutionTime)# ms<br>
                Records Returned : #evaluate(RecordsReturned)#
            </div>
            
            </cfoutput>

            </td>
        </tr>

    </cfif>
    <!--- END DIAGNOSTIC SETUP: ----------------------------------------------------------------- --->

    <!--- BEGIN PAGING SETUP: ----------------------------------------------------------------- --->

    <cfif attributes.RecordsPerPage neq "">
    <tr>
        <td colspan=
"<cfoutput>#diagColumnWidth#</cfoutput>">
            <!--- // ----------------------------------------------------------------- // --->
            <!--- A small internal table to keep our formatting intact --->

            <table width="100%" align="center">
                <tr>
                    <td align=
"left">
                    <cfif PreviousPage gte 0>
                        <a href="?ThisPage=<cfoutput>#PreviousPage#</cfoutput>">Previous</a>
                    <cfelse>
                        Previous
                    </cfif>
                    </td>
                    <!--- // ----------------------------------------------------------------- // --->
                    <td align="center">
                        Pages :
                        <cfloop index="pages" from="0" to="#TotalPages-1#">
                            <cfoutput>
                                <cfif URL.ThisPage eq pages>
#pages+1#<cfelse><a href="?ThisPage=#pages#">#pages+1#</a></cfif>
                            </cfoutput>
                        </cfloop>

                    </td>
                    <!--- // ----------------------------------------------------------------- // --->
                    <td align="right">
                        <cfif (TotalPages-1) gt URL.ThisPage>
                            <a href="?ThisPage=<cfoutput>#NextPage#</cfoutput>">Next</a>
                        <cfelse>
                            Next
                        </cfif>
                    </td>
                    <!--- // ----------------------------------------------------------------- // --->
                </tr>
            </table>


            <!--- // ----------------------------------------------------------------- // --->
            </td>
        </tr>

    </cfif>
</table>
<!--- End of ExecutionMode for this custom tag --->
</cfif>

<!---
Now that you have most of the work done you can save this file in the same folder or coldfusion's custom tag folder.
If you find this useful and want to use in other applications, use the coldfusion's custom tag folder
--->

-----------------------------------------------------------------------------------
PAGING_TESTER.CFM
-----------------------------------------------------------------------------------
<!---
This is the calling page. All you need to do here is query the database as usual, then call our custom tag.
Technically, for basic functionality, thats about 5 lines of code that you will write from this page on and every other template to render a query output...
Thats it.
Follow along.
--->

<!--- QUERY: --->
<cfquery name="qtest" datasource="SpacePro">
    select * from mytable
</cfquery>
<!--- QUERY: --->

<!---
NOTE: since we are using "select *" in our query, the resulting column list is going to be ordered by column names. If you do not want that, a simple workaround is to setup columnlist yourself, like;
<cfset myColumnList = "col5, col4, col10, col9, col11,"> (so 6 lines of code, thats not so bad...)
The you can use "SelectedColumns="#myColumnList#" " as the custom tag attribute
--->

<!--- call the custom tag here --->

<cf_paging QueryName="qTest" SelectedColumns="#qTest.columnList#" ShowDiagnostics="false" ShowRowCount="true" RecordsPerPage="25">
    <!--- All code inserted here will go on top of the table displayed --->
    <!--- For example Style sheet for the navigation pane can be inserted here --->


All ColdFusion Tutorials By Author: Anang A Phatak
  • A DataSet just like VB.Net
    This tutorial shows you how to create a "dataset" just like the one in VB.Net In VB.Net you would create a dataset with "edit" button in an extra column. Once you click "edit", you get an option to "update", "delete" or "cancel edit mode" This is just like a cfgrid tag. Although a cfgrid tag lets you bulk insert, bulk update or bulk delete, the dataset object does it one by one. But cfgrid is slower, and may give users Java errors, depending on their browser settings.
    Author: Anang A Phatak
    Views: 14,675
    Posted Date: Wednesday, November 17, 2004
  • A Mp3 Streaming Server
    This is a small application that shows you how to create an MP3 streaming server.
    Author: Anang A Phatak
    Views: 11,821
    Posted Date: Monday, November 8, 2004
  • A plot to plot a line
    I had no work one day due to a worm attack on our servers, thus a plot to plot a line on a graph was hatched in my empty mind. These files show you, how to plot a line using no database, no java, no long wait times for aplet loading, just 3 tools, Loop, table and text.
    Author: Anang A Phatak
    Views: 7,730
    Posted Date: Thursday, May 6, 2004
  • A random password generator
    RANDOM PASSWORD GENERATOR SCRIPT ! I know there is a random password tutorial here already. This is just another way to do the same. I think this is a little easier to understand. Refresh it to generate a new password string everytime !
    Author: Anang A Phatak
    Views: 9,393
    Posted Date: Monday, May 24, 2004
  • Advanced Calculator
    I have posted a "Basic Calculator" tutorial here. That was more like a representation of how you would calculate with a paper and a pencil. You provide INPUT A then a MATHEMATICAL OPERATION like a "+" or a "-" and then an INPUT B. This is more a represntation of how you would use a regular hand-held calculator complete with buttons for NUMBERS, OPERATIONS and CLEAR TEXT.
    Author: Anang A Phatak
    Views: 8,602
    Posted Date: Friday, June 18, 2004
  • Automatic Form Generator
    This is not a tutorial as such, more like an application that you can put in a directory. It could boring if you use the CF editor, to pick "cfform" fill its attributes, then pick "cfinputs" one by one. fill out those attributes... one by one, then change tabs and pick the "submit" button... so on and so forth. Even if you code in a note pad, it might get lengthy to code individual element. Wouldn't it be nicer to code all these elements at once, then just copy the code and paste it in your editor?
    Author: Anang A Phatak
    Views: 9,033
    Posted Date: Thursday, May 20, 2004
  • Automatically Query To CFM
    This is a custom tag application. The cf_QueryRender custom tag takes your query arguments and gives you a final page table and all...
    Author: Anang A Phatak
    Views: 11,062
    Posted Date: Friday, October 29, 2004
  • Breaking down your query results into pages (Paging Tutorial)
    I havent come across a "paging" tutorial on this site. I know there are JavaScripts available that help you achieve this, and the DataSet object in VB.Net comes with paging. All you do is "enable paging". But how do you do it in ColdFusion ?
    Author: Anang A Phatak
    Views: 14,646
    Posted Date: Tuesday, November 16, 2004
  • Breaking down your query results into pages (Paging Tutorial) Part-II
    This is an extension to my last tutorial "Breaking down your query results into pages (Paging Tutorial)" which is posted here on www.easycfm.com In the last tutorial, you could retrieve a dataset with a , then use a technique to seperate the results over several pages. It simply ; - took the total "recordCount" - divided that with the "number of records per page" - then displayed the number of pages at the bottom of the table. This is a little more sophisticated than that. Read on...
    Author: Anang A Phatak
    Views: 7,459
    Posted Date: Wednesday, January 11, 2006
  • ColdFusion MX 6.1 Installation on Linux (Ubuntu -- Hoary Hedgehog)
    I have tried hoards of websites on how to install coldfusion on Fedora Core 3 with apache webserver. For some reason the connectors always failed. I had "Ubuntu" on my laptop, basically because "acpi" suspend/hibernate actually works. I decided I might try to install CF there to find out what was going wrong. Surprisingly everything worked like a charm. Make sure you use "apt-get install apache2" before you try this. BEST OF LUCK ....
    Author: Anang A Phatak
    Views: 9,169
    Posted Date: Tuesday, May 10, 2005
  • Dynamic textbox and progress bar for your pages
    The principle of this tutorial is similar to "Dynamic time and date for your pages" tutorial. Except that this one generates messages, and that one updated time. Read on, you will get the hang of it....
    Author: Anang A Phatak
    Views: 11,290
    Posted Date: Thursday, May 19, 2005
  • Dynamic time and date for your pages
    Have you seen the "www.EasyCFM" page closely? On the main page, top right, there is a place for time, and top left a place for day-date. Ever wonder how Pablo does it ? This is not a ColdFusion tutorial. Its JavaScript.
    Author: Anang A Phatak
    Views: 9,256
    Posted Date: Wednesday, January 5, 2005
  • Getting ColdFusion Studio for Linux
    I like using HomeSite+ for windows, and I am getting used to Dreamweaver Mx. But I still need something just as good for Linux. For some reason, I couldnt get "wine and Dreamweaver Mx" to work. So I "Googled" a bit and stumbled upon Eclipse and cfEclipse. Here is how to set it up.
    Author: Anang A Phatak
    Views: 10,338
    Posted Date: Wednesday, May 25, 2005