Skip to main content

How to implement data pagination in jMaki tables

Posted by carlavmott on September 19, 2007 at 5:31 PM PDT

The question about paging through data in a table comes up enough that I decided to answer in a blog. Using some code Greg posted in an email a few months back let's create a simple example of paging through data in a table. In this example, we will use the Dojo fisheye widget to drive the pages that are displayed in a Dojo table. Each time the user clicks on an icon the table displays different parts of the data depending on the icon clicked. Most of the work for determining what to display is done in JavaScript code. The data is in a JSP file but can be in some serverside component that returns the data in JSON format. We will use the jmaki.doAjax call to get the data when the page loads.

I created the index page with the standard jMaki layout and added the Dojo fisheye widget in the left side bar and the Dojo table widget in the main area. In this case we will not provide any data for the rows but rely on the paging mechanism to supply all data. index.jsp looks like:

            <div id="main">
                <div id="leftSidebar">
                   
                <a:widget name="dojo.fisheye" args="{orientation:'vertical'}" value="[
     {iconSrc:'https://ajax.dev.java.net/images/blog_murray.jpg',
      label : 'Page 1',
      action : { message : {value : 'books1'}}
     },
     {iconSrc:'https://ajax.dev.java.net/images/chinnici.jpg',
      label : 'Page 2',
      action : { message : {value : 'books2'}}
     },
      {iconSrc:'https://ajax.dev.java.net/images/JayashriVisvanathan.jpg',
      label : 'Page 3',
      action : { message : {value : 'books3'}}
     }         ]"/>

                   
                </div> <!-- leftSidebar -->

                <div id="content" style="height:400px">
                   
                
                    <a:widget name="dojo.table"
                    subscribe="/datatable"
                    publish="/datatable"
                    value="{columns : [
     { label : 'Title', id : 'title'},
     { label :'Author', id : 'author'},
     { label : 'ISBN', id : 'isbn'},
     { label : 'Description', id : 'description'}
     ],
     rows : [
     ]
     }" />

    
            </div> <!-- content -->
       
            </div> <!-- main -->

Some things to note. The fisheye widget publishes to the topic '/dojo/fisheye' unless it is over written. In this case we use the default. Remember that the user will click on an icon in the fisheye and that will result in loading different pages of data. The way that I communicate the page to load is by using an action. In this case I use a strings 'book1', 'book2' and 'book3' to identify the page. The strings are passed using the property 'value'. Finally, notice I reset both subscribe and publish attributes for the table widget. More on this later.

Next I created a JSP called books.jsp which contains all the data we're going to use. The data is already in JSON format. books.jsp looks like:

[
[
  { id : 'i1', title : 'Book Title 1', author : 'Author 1', description : 'A look at the samples ', url : 'https://ajax.dev.java.net/samples'},
  { id : 'i2', title : 'Book Title 2', author : 'Author 2', description : 'A Some long description', url : 'https://ajax.dev.java.net/samples'},
  { id : 'i3', title : 'Book Title 3', author : 'Author 3', description : 'A Some long description', url : 'https://ajax.dev.java.net/samples'},
  { id : 'i4', title : 'Book Title 4', author : 'Author 4', description : 'A Some long description', url : 'https://ajax.dev.java.net/samples'},
  { id : 'i5', title : 'Book Title 5', author : 'Author 5', description : 'A Some long description', url : 'https://ajax.dev.java.net/samples'}
],
[
  { id : 'i6', title : 'Book title 6', author : 'Author 2', description : 'A Some long description', url : 'https://ajax.dev.java.net'},
  { id : 'i7', title : 'Book title 7', author : 'Author 2',  description : 'A Some long description', url : 'https://ajax.dev.java.net'},
  { id : 'i8', title : 'Book title 8', author : 'Author 2', description : 'A Some long description', url : 'https://ajax.dev.java.net'},
  { id : 'i9', title : 'Book title 9', author : 'Author 2',  description : 'A Some long description', url : 'https://ajax.dev.java.net'},
  { id : 'i10', title : 'Book Title 10', author : 'Author 2',  description : 'A Some long description', url : 'https://ajax.dev.java.net'}
],
[
  { id : 'i11', title : 'Book Title 11', author : 'Author 3', description : 'A Some long description', url : 'https://ajax.dev.java.net/about'},
  { id : 'i12', title : 'Book Title 12', author : 'Author 3', description : 'A Some long description', url : 'https://ajax.dev.java.net/about'},
  { id : 'i13', title : 'Book Title 13', author : 'Author 3', description : 'A Some long description', url : 'https://ajax.dev.java.net/about'},
  { id : 'i14', title : 'Book Title 14', author : 'Author 3', description : 'A Some long description', url : 'https://ajax.dev.java.net/about'},
  { id : 'i15', title : 'Book Title 15', author : 'Author 3', description : 'A Some long description', url : 'https://ajax.dev.java.net/about'}
]
]

The data is formated as an array of arrays of objects. Each array of objects is a page of data. Most of the ids in the data should look familiar as they map to the columns. The last element is a url. It is not represented on the page but can be used. As you will see we will write the code so when the user clicks on the row we will navigate to that url. In order to get that url we need to write a handler for the onSelect event for a table. The handler will be listening to the '/datatable/ topic and that is why we added a publish argument to the table tag.

Finally I updated the glue.js file to add the JavaScript code for getting the data and providing the appropriate data for the table.
The JavaScript code follows:

/*
* These are some predefined glue listeners that you can
*  modify to fit your application.
*
* This file should not placed in the /resources directory of your application
* as that directory is for jmaki specific resources.
*/

// uncomment to turn on the logger
jmaki.debug = true;
// uncomment to show publish/subscribe messages
jmaki.debugGlue = true;


var books; // load using an ajax request

jmaki.doAjax({
  url : "books.jsp",
  callback : function(req) {
   books = eval(req.responseText);
   jmaki.log("Loaded Books " + books);
  }
});



// map to the defualt topic /dojo/fisheye to fisheye handler
jmaki.subscribe("/dojo/fisheye*", function(args) {
    switch (args.message.value) {
        case  'books1' : {
            // clear the rows
            jmaki.publish("/datatable/clear", {});
            jmaki.publish("/datatable/addRows", { value : books[0]});
            return;
        }
        case  'books2' : {
            // clear the rows
            jmaki.publish("/datatable/clear", {});
            jmaki.publish("/datatable/addRows", { value : books[1]});
            return;
        }
        case  'books3' : {
            // clear the rows
            jmaki.publish("/datatable/clear", {});
            jmaki.publish("/datatable/addRows", { value : books[2]});
            return;
        }

    }
});

// the handler for the datatable
jmaki.subscribe("/datatable/onSelect", function(args) {
/*    var row = getRow(args.targetId);
    if (row){
        jmaki.log("url=" + row.url);
        window.location.href = row.url;
    }
    */
    if(args.value && args.value.url){
        jmaki.log("url=" + args.value.url);
        window.location.href = args.value.url;
    }
});

// find the row
function getRow(targetId) {
  for (var i=0; i < books.length; i++) {
      for (var ii=0; ii < books[i].length; ii++) {
          if (books[i][ii].id == targetId) return books[i][ii];
      }
  }

}

The first thing that happens is I make a jamki.doAjax() call to get the data and store it locally. Then I define two handlers to manipulate the data. I subscribe to '/dojo/fisheye' and based on which string I get (book1, book2, book3) I publish the appropriate section of data to the '/datatable' topic which the Dojo table is subscribed. This way I control what is loaded into the table. Since I formated the data in way that matches the table data model paging becomes really easy.

I also have a handler for the onSelect event from the table. When the user clicks on a row the table widget will automatically publish the id of the row that was selected. There have two ways of getting the url. Since this is a table widget the data of the selected row is included in the payload so I can just look at the value of the url property. The second way to find the url is to get the targetId property which tells me the id of the thing that was selected (true for all onSelect events) and use that to traverse through the data and find the appropriate row. Then I can just access the url property. I included the code for both since both are useful.

Tha's it. You now have a way of paging through the data in the table widget in jMaki.

Related Topics >>