- The Book of Dojo
- Quick Installation
- Hello World
- Debugging Tutorial
- Introduction
- Part 1: Life With Dojo
- Part 2: Dijit
- Part 3: JavaScript With Dojo and Dijit
- Part 4: Testing, Tuning and Debugging
- Part 5: DojoX
- The Dojo Book, 0.4
Pagination
Submitted by criecke on Sat, 05/12/2007 - 12:23.
As shown in the other datastore sections, the fetch method of the Read API can query across and return sets of items in a variety of ways. However, there is generally only so much space on a display to list all the data returned. Certainly, an application could implement its own custom display logic for just displaying subsets of the data, but that would be inefficient because the application would have had to load all the data in the first place. And, if the data set is huge, it could severely increase the memory usage of the browser. Therefore, dojo.data provides a mechanism by which the store itself can do the paging for you. When you use the paging options of fetch, all that is returned in the callbacks for fetch is the page of data you wanted, no more. This allows the application to deal with data in small chunks, the parts currently visible to you.
The paging mechanism is used by specifying a start
parameter in the fetch arguments. The start
parameter says where, in the full list of items, to start returning items. The index 0 is the first item in the collection. The second argument you specify is the count
argument. This option tells dojo.data how many items, starting at start
, to return in a request. If start
isn't specified, it is assumed to be 0. If count
isn't specified, it is assumed to return all the items starting at start
until it reaches the end of the collection. With this mechanism, you can implement simple paging easily.
To demonstrate the paging function, we'll assume an ItemFileReadStore with the following datasource:
{ identifier: 'name', items: [ { name: 'Adobo', aisle: 'Mexican' }, { name: 'Balsamic vinegar', aisle: 'Condiments' }, { name: 'Basil', aisle: 'Spices' }, { name: 'Bay leaf', aisle: 'Spices' }, { name: 'Beef Bouillon Granules', aisle: 'Soup' }, ... { name: 'Vinegar', aisle: 'Condiments' }, { name: 'White cooking wine', aisle: 'Condiments' }, { name: 'Worcestershire Sauce', aisle: 'Condiments' } { name: 'pepper', aisle: 'Spices' } ] }
The following code snippet would allow for paging over the items, 10 at a time:
var store = new dojo.data.ItemFileReadStore({url: "pantryStore.json" }); var pageSize = 10; var request = null; var outOfItems = false; //Define a function that will be connected to a 'next' button var onNext = function(){ if(!outOfItems){ request.start += pageSize; store.fetch(request); } }; //Connect this function to the onClick event of the 'next' button //Done through dojo.connect() generally. //Define a function will be connected to a 'previous' button. var onPrevious = function(){ if (request.start > 0){ request.start -= pageSize; store.fetch(request); } } //Connect this function to the onClick event of the 'previous' button //Done through dojo.connect() generally. //Define how we handle the items when we get it var itemsLoaded = function(items, request){ if (items.length < pageSize){ //We have found all the items and are at the end of our set. outOfItems = true; }else{ outOfItems = false; } //Display the items in a table through the use of store.getValue() on the items and attributes desired. ... } //Do the initial request. Without a query, it should just select all items. The start and count limit the number returned. request = store.fetch({onComplete: itemsLoaded, start: 0, count: pageSize});
Note: The previous sample shows how the fetch()
function returns a request
object. According to the dojo.data specification, the request object contains the query parameters passed in plus an abort()
function appended to it. In general, the abort function is intended for cases in which a request might take too much time to process or, in using the streaming callback of fetch()
, a way to stop the streaming.
The request object also serves another purpose for datastores. It is a location where the store can cache hidden information about the request in process, such as a cache entry key for boosting performance through specifying exactly what internal cache might be in use for this particular query. Therefore, datastores can avoid calls to the server if possible. And, in the paging case, it becomes important to reuse the request object returned from fetch()
. Also note that not all stores will append cache information to the request, but some might. Therefore, when in doubt, reuse the request object when paging.
- Printer-friendly version
- Login or register to post comments
- Subscribe post
Is there any way to specify the total number of items returned?
I need to be able to perform random pagination on a data store. This means that it is necessary to know the total number of results retrieved before requesting them. The provided example only allows pagination from one page to the next, not something similar to the Array "length" property. Does the dojo.data API support this?
Thanks
Shane
The onBegin callback is a
The onBegin callback is a point where the store can tell you how many total records matched the query:
See dojo.data.api.Read.fetch():
// The *onBegin* parameter.
// function(size, request);
// If an onBegin callback function is provided, the callback function
// will be called just once, before the first onItem callback is called.
// The onBegin callback function will be passed two arguments, the
// the total number of items identified and the Request object. If the total number is
// unknown, then size will be -1. Note that size is not necessarily the size of the
// collection of items returned from the query, as the request may have specified to return only a
// subset of the total set of items through the use of the start and count parameters.
Though, after reading the API docs there, that may not be perfectly clear. The point of onBegin is a function that tells you that the item retrieval/query has begun, and how many total items have been identified that matched the query passed. This is not the same as items.length of onComplete, as onComplete's value set is controlled by start and count (how many of the total set to return, starting at some offset).
So, what you can do, is perform a query to just get total number of items by specfying to return a count of 0. onBegin of that call would tell you up front how many total matches there were, providing the store can get that information from the provider of the data.
Not for large recordsets
We should mention the important fact, that the current paging logic within ItemFileReadStore don't affect the call to the server script:
Therefore the paging mechanism works only on the side of the Client and is not recommended for big recordsets on the Server.
Remi
It should also be noted that
It should also be noted that ItemFileReadStore is only one store implementation. Its design is to load everything and do all sorting/paging in the client. It is not intended for gargantuan record sets. It is not intended as the be-all-end-all store that works for every possible scenario. For large record sets, you would want to implement your own data store that can communicate the paging request information to your back end service and let the back end handle the sorting and paging for you.
Please consider adding a fromEnd query option
A fromEnd query option would be used to specify that the start location is relative to the end of the list rather than the beginning of the list. This would be useful when the list is updated frequently (e.g. a mail inbox) and would allow navigation to the end of the list without having to first query the server for the number of items in the list.
Example:
request = store.fetch({onComplete: itemsLoaded, start: 0, count: pageSize, fromEnd: true});