Creating a Custom Dojo Widget

A Typical pagination widget should have links to navigate between pages. Generally First, Next, Previous & Last are the four links that will be present in a pagination widget.

Custom Widget - First Step
Create a Javascript file, named Paginator.js (For simplicity sake, keep this file under dijit folder)
Skeleton code for Paginator.js
dojo.provide("dijit.Paginator");
dojo.require("dijit._Templated");
dojo.require("dijit.layout.ContentPane");

dojo.declare("dijit.Paginator",
	[dijit.layout.ContentPane, dijit._Templated], 
{
});


The above code creates a widget by name dijit.Paginator, and tells dojo that a widget by this name is now available.

Adding functionality to the widget.
Creating the required HTML snippet for the widget.


This is the HTML code that the widget will use to display on the browser.
There are two ways of letting dojo engine know about using this HTML code for rendering on browser. Using templateString property, or templatePath property of the widget.
For this example, templateString is used to provide the HTML code for the widget.
dojo.declare("dijit.Paginator",
	[dijit.layout.ContentPane, dijit._Templated], 
{
	templateString: '
' + '
' + ' ' + ' |<' + '   ' + ' ' + ' <<' + '   ' + '  ' + ' ' + ' >> ' + '  ' + ' ' + ' >|' + ' ' + '
' + '
' });

The html required by the widget is assigned to a property templateString, this property is the one used by dojo when rendering/parsing the widget on the browser. (templatePath can also be used, by providing path for HTML file) dojoAttachEvent is the way of attaching an event handler for any node (HTML node/tag).
Adding the required properties for the widget.
	currentPage: 1,
	totalPages: 0,

These are two properties that will be initiated by the pages using the widget.
Adding a method for refreshing the widget according to the current state of the widget. Meaning, the first/prev links should be hidden when the page shown is the first page, and similar case with last/next links. Here is the code for refresh method.
	refresh: function () {
		if(this.currentPage <= 0) this.currentPage =1;
		this.pageNumInfoNode.innerHTML = this.currentPage + " of " + this.totalPages;

		if(this.currentPage == 1) {
			this.prevNode.style.display = "none";
			this.firstNode.style.display = "none";
		} else {
			this.prevNode.style.display = "";
			this.firstNode.style.display = "";
		}

		if(this.currentPage >= this.totalPages) {
			this.nextNode.style.display = "none";
			this.lastNode.style.display = "none";
		} else {
			this.nextNode.style.display = "";
			this.lastNode.style.display = "";
		}
		
	}

pageNumInfoNode points to the node in the widget, which displays the current page number. It shows the information, something like "1 of 5", "3 of 10" etc.,
Whenever a dojo widget has been rendered & created on browser, dojo engine calls the postCreate method of the widget to perform any operations upon creation of the widget. This method can be generally used for initializing state of the widget. Use this method for refreshing/initializing the widget for the initial view.
	postCreate: function(){
		this.refresh();
		this.inherited(arguments);
	}

this.inherited(arguments) calls the super/parent widgets postCreate up the hierarchy. (Similar to super in java).
Add event handlers for each of the pagination links.
	firstClick: function () {
                if(this.currentPage <= 1) return;
		this.currentPage = 1;
		this.refresh();
		this.onPageChange(this.currentPage);
	},
	prevClick : function() {
                if(this.currentPage <= 1) return;
		this.currentPage = this.currentPage - 1;
		this.refresh();
		this.onPageChange(this.currentPage);
	},
	nextClick : function() {
                if(this.currentPage >= this.totalPages) return;
		this.currentPage = this.currentPage + 1;
		this.refresh();
		this.onPageChange(this.currentPage);
	},	
	lastClick: function () {
                if(this.currentPage >= this.totalPages) return;
		this.currentPage = this.totalPages;
		this.refresh();
		this.onPageChange(this.currentPage);
	},

onPageChange will be the way of the widget to communicate with outer world. Whenever user does any activity on the widget, like changing the page, onPageChange event will be triggered and it passes the current page number as the parameter. Then the page can take required actions to show the data appropriate for that page number.
Anyway, there should be a default implementation for this onPageChange method in the widget.
So, here is the default implementation of onPageChange, which should and must be overridden by page using the widget to get any meaningful functionality.
	onPageChange: function (currPage) {
		// User should override this method to communicate with the widget & perform required actions for particular page.

	},

Putting it all together, Here is the complete code for Paginator.js
dojo.provide("dijit.Paginator");

dojo.require("dijit._Templated");
dojo.require("dijit.layout.ContentPane");

dojo.declare("dijit.Paginator",
	[dijit.layout.ContentPane, dijit._Templated], 
{

	
	templateString: '
' + '
' + ' ' + ' First ' + '   ' + ' ' + ' Prev ' + '   ' + '  ' + ' ' + ' Next ' + '  ' + ' ' + ' Last ' + ' ' + '
' + '
', currentPage: 1, totalPages: 0, firstClick: function () { this.currentPage = 1; this.refresh(); this.onPageChange(this.currentPage); }, prevClick : function() { this.currentPage = this.currentPage - 1; this.refresh(); this.onPageChange(this.currentPage); }, nextClick : function() { this.currentPage = this.currentPage + 1; this.refresh(); this.onPageChange(this.currentPage); }, lastClick: function () { this.currentPage = this.totalPages; this.refresh(); this.onPageChange(this.currentPage); }, onPageChange: function (currPage) { // User function called. passes the currentPage }, refresh: function () { if(this.currentPage <= 0) this.currentPage =1; this.pageNumInfoNode.innerHTML = this.currentPage + " of " + this.totalPages; if(this.currentPage == 1) { this.prevNode.style.display = "none"; this.firstNode.style.display = "none"; } else { this.prevNode.style.display = ""; this.firstNode.style.display = ""; } if(this.currentPage >= this.totalPages) { this.nextNode.style.display = "none"; this.lastNode.style.display = "none"; } else { this.nextNode.style.display = ""; this.lastNode.style.display = ""; } }, postCreate: function(){ this.refresh(); this.inherited(arguments); } });
Example of using the newly created widget.




In this example, whenever the user clicks on any of the links on the widget, notification is sent to myFunction which notifys the page change.

No comments:

Post a Comment