Easy AJAX Pagination Using JQuery

by daphonz
This simple little JQuery function allows you to drop paginated data into your views with ease.
I chose to implement ajax pagination in this manner because I wasn't able to successfully follow Rob Conner's technique in his super-useful Advanced Pagination article (http://bakery.cakephp.org/articles/view/advanced-pagination-1-2).

I assume in this article that you are familiar with basic pagination techniques using Cake's built-in functions. If you are not, make sure to read and understand those first.

I use the following to display a paginated list of related items in a sidebar element, though I imagine it can easily generalize whatever you'd like it to do.

Let's begin.

Things you will need:

  1. CakePHP 1.2.6311 or later
  2. JQuery 1.2.3 (http://docs.jquery.com/Downloading_jQuery)
  3. Data you want to paginate

Download JQuery, and put it in your /app/webroot/js/ folder. Include it in the header of your view, i.e.:


echo $javascript->link(array('jquery.js'));

In the controller providing paginated data, be sure to include the RequestHandler Component. For the purposes of this example, I'm going to be paginating Images in an ImageController. So my basic controller looks something like this:


Controller Class:

<?php 
class ImagesController extends AppController
{
    var 
$components = array('RequestHandler');
    var 
$helpers = array('Html','Form','Javascript');
    var 
$paginate = array('order'=>array('Image.title'),'limit'=>'15');

        function list()
        {
                
$data $this->paginate();
                
$this->set('images',$data);
        }

}
?>

And the view is equally simple (/app/views/images/list.ctp):

View Template:


<?php
if (count($images)>0) {
     
/* Display paging info */
?>
<div id="pagination">
<?php
      
echo $paginator->prev(); 
      echo 
$paginator->numbers(array('separator'=>' - ')); 
      echo 
$paginator->next();
?>
</div>

<table>
<?php
      
foreach ($images as $image) {
?>
      <tr>
             <td>
<?php
           
echo $html->image($image['Image']['filename']);
?>
            </td>
            <td>
                      <?php echo $image['Image']['title'];?>
            </td>
     </tr>
<?php
      
}
?>
</table>
<?php
}
?>

This would be your basic level of pagination. Note the Div around the pagination-specific links.

Now let's say that I'm in another controller, and I'd like to see a paginated list of all my Images.

So here's where the JQuery magic comes in. First, designate a part of your view you want to use to display the image pagination with a div.

Say I'm in a view where I'm adding content, ie: /app/views/content/add.ctp:

View Template:



/* bunch of related content view code, etc, etc, then.... */

<div id="imageList">

</div>



Now include this snippet of Javascript before the div:

View Template:



/* bunch of related content view code, etc, etc, then.... */
    <script type="text/javascript">
          $(document).ready(function() {
            loadPiece("<?php echo $html->url(array('controller'=>'images','action'=>'list'));?>","#imageList");
             });
    </script>
<div id="imageList">

</div>

The $(document).ready() function is from JQuery. The Javascript function, loadPiece, needs to be included either in the head of your view, or in a reference file. Here it is (it also requires JQuery):


/**
 * Loads in a URL into a specified divName, and applies the function to
 * all the links inside the pagination div of that page (to preserve the ajax-request)
 * @param string href The URL of the page to load
 * @param string divName The name of the DOM-element to load the data into
 * @return boolean False To prevent the links from doing anything on their own.
 */
function loadPiece(href,divName) {    
    $(divName).load(href, {}, function(){
        var divPaginationLinks = divName+" #pagination a";
        $(divPaginationLinks).click(function() {     
            var thisHref = $(this).attr("href");
            loadPiece(thisHref,divName);
            return false;
        });
    });
}

This function loads a particular URL using an Ajax-request (in this case, the Image Controller's list() function), and writes it to the specified DIV. The RequestHandler component makes sure that Cake only renders the view, sans any layout templating.


For all links within the pagination div the function applies an event listener so that, when clicked, the link URL is loaded through JQuery's Ajax loader and back into the specified DIV. Any links not in this div will load in a normal way, though, as you can see, it's pretty easy to change the behavior.


I like this method quite a bit, as it just makes more sense to me, and it's also quite clean.

Report

More on Snippets

Advertising

Comments

  • hanx posted on 06/02/11 09:01:20 PM
    Woww..great article.. it's working great..
    but is it possible to add a loader image in this pagination?
  • ernestocuzcueta posted on 03/21/11 11:01:36 PM
    The article is great. I will implement this in my system and I will use this idea for other places. But I can't see how you in the system define when not use the layout of the page. I suppose you have a default layout with the header and other html text and when you make the request by ajax you only want the content of the list.
    How you define or choose when use the layout or not, because I can see in the code any flag or variable in the URL


    Regards and thanks
  • chetanspeed511987 posted on 03/08/11 01:50:22 PM
    Its excellent
  • raxit4u2 posted on 04/29/10 02:35:10 AM
    Hello friends,

    Thanks for superb code for paging and sorting.

    Unfortunately, this is not working for me in Mozilla Firefox.
    I searched a lot and getting Clear Cache and Cookie like solution. But neither works for me. Finally i found this link and got the problem solved. Problem is with jQuery load function. Below is the link.

    http://frd.im/DR2ovj
    Hope i helped you.

    Thanks,
    Rakshit Patel.
  • ryanoff posted on 04/27/10 09:12:20 AM
    Great article. I also struggled to get the Advanced Pagination working, but with your article I was able to get it working in 2 minutes.
  • Casmo posted on 04/27/10 05:05:34 AM
    Thanks for the article!

    I have modified it a little:

    $(document).ready(function() {
        // The div where <?php echo $paginator->numbers(); ?> is located
        $('div#results_pages a').click(function(){
            var thisHref = $(this).attr("href");
            // The content div
            $('div#content_search').load(thisHref);
            return false;
        });
    });
  • edimov posted on 07/21/09 03:52:23 AM
    Just a small addition:

    Since the ids of the paginator are hardcoded, you might want use the jquery.find(), i.e.


        $(divName).load(href, {}, function(){
            $(divName).find("a").each(function(i){
              $(this).bind('click', function(){
                var thisHref = $(this).attr("href");
                loadPiece(thisHref,divName);
                return false;
              });
            });
        });
    It was fine for me since I did not want any links on the loaded div outside ajax.

    Thanks for the cool function Casey.
  • bhavna posted on 04/01/09 02:56:02 AM
    Well, that’s all there is to it. I know this post doesn’t go into a lot of detail and code specifics, but it should give you a good general idea on how to setup such a filter with AJAX. Definitely try out the method described above to do an AJAX pagination, it is simple, effective and allows you to create really cool interactive widgets like this one for your data filters.
    http://www.probabilites-du-poker.fr
  • meshach posted on 02/03/09 10:33:19 AM
    This gives me full tables, because it's routing through the controller and view. It'd be nice to know how to implement this with a related table. For example, maybe using this to load an element to which you can send an array? Thanks!
  • atlantis posted on 07/27/08 05:24:31 PM
    Thanks for a great article!

    I also wasn't able to make the Advanced Pagination work, so tried this one and I've got working AJAX pagination in a minute!
login to post a comment.