A while ago I promised a demo showing how to use Spry's new PagedView feature to combine client and server side paging. Taking the "walk before you run" lesson to heart - I decided to first show a demo of how to do server side paging with Spry. This would be useful for huge datasets.

Let's first start with the server side code. I wanted something you guys could download and play with, so the server side code is not using a database. Anyway - here is the code:

<cfsetting enablecfoutputonly="true" showdebugoutput="false"> <cfparam name="url.start" default="1"> <cfparam name="url.end" default="100">

<cfset total = 1000>

<cfif url.start gt total> <cfset url.start = total> </cfif>

<cfif url.end gt total> <cfset url.end = total> </cfif>

<cfcontent type="text/xml"><cfoutput><?xml version="1.0" encoding="UTF-8"?><people><cfloop index="x" from="#url.start#" to="#url.end#"><person><id>#x#</id><name>Name #x#</name></person></cfloop></people></cfoutput>

I begin with a cfsetting to reduce the whitespace. This is important when returning XML. I then have two cfparams. One for the start row and one for the end row. I default these to sensible values.

Next I have a "total" value. This wouldn't be hard coded but would rather come from the database. (Don't forget my MySQL tip on how you can get a total and a page all in one query.)

Since I know how many rows of data I have - I can then do sanity checks on start and end. Now I'm ready to generate my XML. Since I'm not using a database I've done a simple cfloop that "fakes" my data. I'm assuming folks have no questions on this so I'll move on.

The client side is a bit more complex than a simple Spry dataview. As before I'll show you the code than walk through what I did:

<script type="text/javascript" src="/spry/xpath.js"></script> <script type="text/javascript" src="/spry/SpryData.js"></script>

<script type="text/javascript" > var start = 1; var perdatapage = 20; var end = start + perdatapage;

var baseurl = "testdata.cfm?";

function getURL() { var s = baseurl; s+="start="+start; s+="&end="+end; return s; }

var mydata = new Spry.Data.XMLDataSet(getURL(),"//people/person");

Spry.Data.Region.debug=false;

function goBack() { start=start-perdatapage; if(start < 1) start=1; end = start+perdatapage; mydata.setURL(getURL()); mydata.loadData(); }

function goForward() { start=start+perdatapage; end = start+perdatapage; mydata.setURL(getURL()); mydata.loadData(); } </script>

<div id="mydata" spry:region="mydata">

<table border="1" width="500"> <tbody spry:repeat="mydata"> <tr> <td>ds_RowID={ds_RowID}</td> <td>id from db={id}</td> <td>{name}</td> </tr> </tbody> <tr align="right"> <td colspan="3"> <a href="javaScript:goBack()"><< Previous</a> | <a href="javaScript:goForward()">Next >></a> </td> </tr> </table> </div>

Ok, lots to cover here. I'm going to skip over the things that I assume most folks know - like the first two script tags that include the main Spry libraries. Let's begin by looking at how we track where we are in the dataset:

var start = 1; var perdatapage = 20; var end = start + perdatapage;

var baseurl = "testdata.cfm?";

function getURL() { var s = baseurl; s+="start="+start; s+="&end="+end; return s; }

These lines initialize my start, end, and page size variables. Because my server side code accepts a start and end value, I created a helper function, getURL(), that will generate my URL for me. This was just for convenience. I use this in my dataset creation line:

var mydata = new Spry.Data.XMLDataSet(getURL(),"//people/person");

So skipping ahead a bit - you can see where I use a simple table to output the values from the XML. Notice I show both the ID, which comes from the data, and Spry's ds_RowID value. I do this just to show you the difference between the row in the dataset on the client side and the server side's row ID.

To enable paging, I added two links at the bottom of the table that call JavaScript functions. Let's now take a look at these - first the code to move to the next page:

function goForward() { start=start+perdatapage; end = start+perdatapage; mydata.setURL(getURL()); mydata.loadData(); }

I begin with some simple arithmetic. Then I use setURL() on the dataset. This lets me update the URL, again I use my getURL function. Then loadData() is called which refreshes the dataset. That's it. The code to handle moving backwards is the same - except for some logic to ensure we don't go below 1.

For a demo of this, go here: http://ray.camdenfamily.com/demos/spryserverpaging/

You may also download the code attached to this entry. This code isn't perfect though. It will gladly let you go past the 1k limit. How can we fix that? I'll answer that in the next post.

Download attached file.