Discovering jQuery’s data() function

by David Joly | Tuesday, March 23rd, 2010

If you have programmed an Ajax web app, you know that manipulating the DOM from a callback function is easy. Manipulating data can be a little bit tricky though, because previously declared javascript variables are not available to the callback function. Apparently many developers, myself included, have stored data in the DOM using hidden elements in any way that seems best at the time. jQuery’s data has made this messy practice unnecessary.

Introduction

The example in this tutorial uses the Zend Framework hosted on an Apache virtual host. Please see the Zend Quickstart tutorial to configure this environment. It is assumed the reader has at least a basic understanding of the Zend Framework and jQuery. Also, please note that this code is for demonstration only. Don’t go using it in a project! The files used in this tutorial can be downloaded here.

For this tutorial, I will be walking through a set of javascript functions and jQuery to show you how jQuery data() can be used. We will be making a simple page that renders information about users, including their first and last name, their IDs, and their locations. We will also have a user browser and a form to add new users. For the sake of simplicity, no database is used in this project.

Make the Controller

Our controller will have two actions, index and adduser. The code is brutally simple here because we are pretty much not doing anything. The index action grabs an array of users from the model (in a real project this would use a database), and sends it to the view. The adduser action is simply taking the posted user data and posting it back to the client in json format.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?php
/**
* Used by Discovering jQuery's data()
* 03/23/2010
* @author David Joly
* @link www.zeletron.com/
*/
class March232010Controller extends Zend_Controller_Action
{
    public function init()
    {
    }
 
    public function indexAction()
    {
    	$usersModel = new Application_Model_Users();
    	$users = $usersModel->getUsers();
   	$this->view->users = $users;
    }
 
 
    public function adduserAction()
    {
    	//Disable View for Async Request
    	$this->_helper->viewRenderer->setNoRender();
    	$this->_helper->layout->disableLayout();
 
    	//Response object to post back to client...
    	$response = new stdClass();
    	if($this->getRequest()->isPost()){
    		$user = array(
    			'firstName'	=> $this->getRequest()->getParam('firstName'),	
    			'lastName'	=> $this->getRequest()->getParam('lastName'),
    			'location'	=> $this->getRequest()->getParam('location'),
    			'userId'	=> $this->getRequest()->getParam('userId')		
    		);
    		$response->code = 1;
    		$response->user = $user;
    	}
    	else
    	{
    		$response->code = 0;
    	}
    	echo json_encode($response);
    }
}

Write the XHTML

Here’s the xhtml in our view script. Please note that no data is rendered by a php loop construct, we are saving that for a javascript function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<h1>Discovering jQuery's data()</h1>
 
<h3>Current Users</h3>
<ul id="users"></ul>
 
<h3>Add User Form</h3>
<div>
	<label for="firstName">First Name:</label>
	<input val="" type="text" name="firstName" id="firstName" />
	<label for="lastName">Last Name:</label>
	<input val="" type="text" name="lastName" id="lastName" />
	<label for="location">Location:</label>
	<input val="" type="text" name="location" id="location" />
	<button id="add-user">Add User</button>
</div>
 
<h3>User Browser</h3>
<div id="user-browser"></div>
<button id="previous">Previous</button>
<button id="next">Next</button>

Developing the Ajax App Client

Continuing in our view script,

22
23
24
25
26
27
28
29
<script type="text/javascript">
//Rather than store our user data in a simple variable called "users",
//we will attach our user data to the body tag. It is easily accessed
//by both inline scripts and Ajax callback functions.
$('body').data('users', <?php echo json_encode($this->users)?>);
 
//Render Current Users...
renderUsers();

We have just written our first and last bit of php in the view script that encodes our users array into an array of json user objects. On line 26 we bind this array of user objects to the body element (We can actually use any valid jQuery selector for this.). We then call a function to render our users to the DOM. Before getting to these functions, let’s add a few more necessary lines of code. Including using jQuery data() to track our current user (This will enable us to browse our users one at a time.).

31
32
33
34
35
36
37
38
39
40
//To browse through our users we will need to track the currentUser also.
$('body').data('currentUser', 0);
 
//Show first user in browser...
showUser();
 
//Bind functions to buttons...
$('#previous').click(function(){previous();});
$('#next').click(function(){next();});
$('#add-user').click(function(){addUser();});

Now let’s get to the functions. Here we have functions to render our users:

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
function renderUser(user)
{
     $('#users').append(
         '<li id="userId_' +  user.userId + '">'
	+'First Name: ' + user.firstName + '<br />'
	+'Last Name: ' + user.lastName + '<br />'
	+'Location: ' + user.location + '<br />'
	+'</li>'
     );
}
 
function renderUsers()
{
     var users = $('body').data('users');
     for(var i = 0; i < users.length; i++){
	renderUser(users[i]);
    }
}

In the renderUsers() function we grab our user array using data(). Piece of cake eh?

Now let’s take a quick look at our browser functions. Notice how each function uses data(). If jQuery’s data() reminds you of globals, I would say I agree with you. We don’t need to pass arguments into these functions at all.

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
function showUser()
{
	var users = $('body').data('users');
	var currentUser = $('body').data('currentUser');
	$('#user-browser').html(
		'Viewing user ' + (currentUser + 1) + ' of ' + users.length + '<br />'
		+'UserId: ' + users[currentUser].userId + '<br />'
		+'First Name: ' + users[currentUser].firstName + '<br />'
		+'Last Name: ' + users[currentUser].lastName + '<br />'
		+'Location: ' + users[currentUser].location + '<br />'
	);
	toggleNav();
}
 
 
function previous()
{
	var currentUser = $('body').data('currentUser');
	$('body').data('currentUser', currentUser-1);
	showUser();
}
 
function next()
{
	var currentUser = $('body').data('currentUser');
	$('body').data('currentUser', currentUser+1);
	showUser();
}
 
function toggleNav()
{
	//Disable Next Button if the current user is the last in the array
	if( $('body').data('currentUser') == $('body').data('users').length - 1){
		$('#next').attr('disabled','disabled');
	} else {
		$('#next').removeAttr('disabled');
	}
	//Disable Previous Button if current user is the first in the array
	if($('body').data('currentUser') == 0){
		$('#previous').attr('disabled','disabled');
	} else {
		$('#previous').removeAttr('disabled');
	}
}

Up to this point we haven’t done anything special that can benefit from data(). By rights, we could have used normal javascript variables and passed them around normally. Let’s write the addUser() function and you too will be hooked on jQuery data().

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
function addUser()
{
	var users = $('body').data('users');
	var userId = users.length;
	$.post('/march232010/adduser',
		{
			firstName : $('#firstName').val(),
			lastName : $('#lastName').val(),
			location : $('#location').val(),
			userId : userId
		},
		function(r)
		{
			if(r.code == 1){
				//Post was a success, add user to users array
				var users = $('body').data('users');
				users.push(r.user);
				$('body').data('users',users);
				//Render new user
				renderUser(r.user);
 
				//Display new user in browser
				$('body').data('currentUser', parseInt(r.user.userId)); 
				showUser();
			}
		},
		'json'
	);
}
</script>

Notice how we both access and manipulate our users array using jQuery’s data(), pushing our newly added user onto the users array. Now, go use jQuery data() rather than storing your data in hidden DOM elements.

Comment on this Article

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

Posting Code: You can post code using the <pre> tag. Specify the language in the lang attribute, like this: <pre lang="php"> //Code Goes Here </pre>