Add Pagination Using Dynamic Visualforce Components and SOQL OFFSET

Last week I wrote an article about the new SOQL OFFSET clause. The purpose of the article was to highlight the new SOQL OFFSET functionality. After I completed my example Visualforce page, I got to thinking:  “It would be really cool to use Dynamic Visualforce Components to enhance the pagination experience for the user”

Buttons Using Dynamic Visualforce

So I started out to complete what I thought should be just a simple task.  It ended up being pretty challenging, at least for me, but the end result is very cool.  I’ve added a working demo so you can play with a real page on our Force.com site: Pagination with Dynamic Visualforce

The reason this project got challenging was a “feature” that I learned about Dynamic Visualforce Components. They do NOT SUPPORT the apex:param component. Arghh! What I was hoping to do was create commandButtons that represent the page numbers and then add a parameter so that my Apex Controller would reRender the result set using the user-selected page number. Not so fast buddy!! Salesforce threw a nasty curve ball on that one so it got interesting and became “BLOGworthy”

If you’ve never tried Dynamic Visualforce Components before, this is your chance to learn about them. I love them; probably because I’m much stronger with Apex than Visualforce.

To set the stage, here is our requirement

  • Allow a user to paginate through a bunch of rows in a pageBlockTable that display 20 rows at a time
  • The Visualforce Page should have “Next” and “Previous” buttons and also include “First Page” and “Last Page” buttons
  • Add buttons that represent page numbers so that a user can easily skip to a given page
  • Finally, only display up to 5 page number buttons (if we had 100 pages, we don’t want 100 buttons!)

If you checked out my demo, I hope you’ll agree that I nailed the requirement!

Here are some highlights of the code

The page code is pretty much the same as last weeks example except that we made the pageBlockButtons component dynamic.  The code to do this in the page is simple:

Finally, in the page, I had to make an actionFunction that the commandButtons could call. I wanted to pass a parameter with the button and just have the commandButton reRender but as noted above “that didn’t fly”. Here’s the actionFunction:


The cool stuff is in the controller.

You can download the full code from the demo page but I wanted to explain a few of the items that were “interesting”.

First, I had to add a variable to track if a user selected a page number button.  This is pretty easy:

   public string selectedPage{
      get;
      set{selectedPage=value;}  //set from the parameter in actionFunction
   }

Second, I added a method to my class called getMyCommandButtons().  This is where it got fun and interesting. In a Visualforce page you can just add a reRender parameter as a string like I did above in the actionFunction.  But in reality, the reRender parameter is an object that expects a set of strings.  So here’s a snippet of Apex code showing how you can handle this:

   //looks so easy but it took me a while to figure this out

   //the reRender attribute is a set NOT a string
   Set theSet = new Set();
      theSet.add('myPanel');
      theSet.add('myButtons');

   //then add the set to your button component
   button.reRender = theSet;

In the demo code, I iterate through a bunch of stuff that you’ll have to check out. I do stuff like set the rendered parameter to “false” if it’s more than 5 pages away from the current page. I disable the current page’s button and make it blue so the user knows where they are. And I add an ellipsis (…) before the last page and after the first page to make the buttons separate a bit better. The best thing that I learned was how to call an actionFunction with parameters from a commandButton that is created using Dynamic Visualforce Components.  It’s one line but I spent a lot of time figuring it out:

   btn.onclick = 'queryByPage(\''+string.valueOf(i+1)+'\');return false;';

In the code above “i+1” is the button/page number and queryByPage() is the name of my actionFunction. I tested and tried and test and tried some more with a bunch of “things” before I got this to work. What was happening was when a user clicked a button, the page would refresh twice and on the second time it would reRender without the selectedPage parameter. I finally figured out that the “onclick” event needs to simply “return false”.  That was it.  I was done! And I have code that I’ll reuse a lot.

I hope you find this helpful. As always, if you’re interested in speaking to one of our CRM Consultants or Salesforce Developers you can contact us anytime.  We love this stuff!