jQuery 3 - Working With Data
Written by Ian Elliot   
Monday, 28 November 2016
Article Index
jQuery 3 - Working With Data
Finding and Using Data
Utility Functions

There are some hidden aspects of using jQuery and its data manipulation functions represent hidden gold. If you have struggled to work with data in JavaScript, and with the DOM in particular, jQuery has some functions you really need to know about.

 Available as a Book:

smallcoverjQuery

buy from Amazon

  1. Understanding jQuery
  2. Basic jQuery CSS Selectors
       Extract: The DOM
  3. More Selectors
       Extract: Basic Selectors
  4. The JQuery Object
  5. Filters 
  6. DOM Traversal Filters 
  7. Modifying DOM Objects
       Extract: Modifying The DOM 
  8. Creating Objects & Modifying The DOM Hierarchy
  9. Working With Data
       Extract: Data ***NEW!!!
  10. Forms 
  11. Function Queues
  12. Animation 
  13. jQuery UI
  14. jQuery UI Custom Control
  15. Easy Plugins 
  16. Testing With QUnit
  17. Epilog A Bonus Function

Also Available:

jquery2cover

buy from Amazon

You don't think too much about data in HTML and JavaScript. It is something that is the job of a database or perhaps JSON and Ajax. However, in modern HTML based apps it is common to embed data within tags that is then transferred to the corresponding DOM elements. The idea is that this allows the UI to pass data to the code and this can be used to modify how the code deals with the UI. In modern frameworks this is used to implement extensions to UI elements and features such as data binding. 

First we need to look at the underlying HTML5 dataset API.

The Dataset API

Until HTML5 the way that data was passed from HTML tags to the DOM elements was ad-hoc. You could add any attribute to an HTML tag and it would be converted to an attribute of the corresponding DOM object. 

For example, if you use the tag:

 <button mydata="myvalue">test1</button>

then an IDE such as NetBeans will flag an error because there is no mydata attribute in a button tag. However, if you load the page you will discover that everything works and the DOM object corresponding to the button has a mydata attribute with the value "myvalue". For example if you try:

 alert($("button")[0].getAttribute("mydata"));

i.e. get the button DOM element, notice the [0] which converts the jQuery object to a DOM object, and use the DOM getAttribute method you will discover that it returns the value "myvalue". This also works if you use nothing but jQuery:

 alert($("button").attr("mydata"));

which also displays "myvalue". The reason for showing the two versions is to emphasize that this isn't anything that jQuery is doing. JavaScript supports "expando" properties which roughly means that you can add properties to JavaScript object simply by using them. In the same way, the JavaScript objects created to represent HTML tags also have expando properties and they will also add properties for any non-standard attributes that you include in the tag. 

This is a useful idea, but it lacks any organization. HTML5 introduced a system for naming and using custom attributes as data - the Dataset API. In this the name of the custom attribute always has to start data- so our previous example would have to be data-mydata.

Simple enough but there is one more twist to the story. When the attributes are converted to JavaScript the data- and the dashes are removed. Each dash that is removed after the first results in the next letter being converted to upper case. So in JavaScript data-mydata becomes mydata. Notice that you can add additional dashes to build up unque or more complex naming schemes. For example data-mycompany-mydata and this would become mycompanyMydata.

The "tag" version of the name is often referred to as "dashed" and the property version is called "camel-cased" because of the way the upper case characters stick up in the middle of the word.

To make getting at the data easier the API also adds a new dataset property to all DOM elements which is set to an object containing key value pairs. For example, following:

<button data-mydata-x="myvalue"
        data-mydata-y="10"
        data-mydata-z=20">
test1</button>

you can retieve the data from the DOM element using:

alert($("button")[0].dataset.mydataX);
alert($("button")[0].dataset.mydataY);
alert($("button")[0].dataset.mydataZ);

That is dataset is an object with properties mydataX, mydataY and mydataZ.

You can access the dataset object directly from jQuery but notice that it is a property not an attribute so you would need to use something like:

alert($("button").prop("dataset").mydataX); alert($("button").prop("dataset").mydataY); alert($("button").prop("dataset").mydataZ);

To summarise:

  • You can still use custom attributes in tags and these are converted to custom attributes on DOM elements which can be accessed using jQuery's attr function but this is not standard HTML5

  • HTML5 introduced the Dataset API which adds the dataset property to all DOM elements and a format for the data-* custom attributes.

  • You can add attributes of the form data-name-name-name and so on.
     
  • The dataset property is set to an object containing key/value pairs corresponding data-* attributes and their values.

  • The keys are obtained from the data-* attributes by dropping the data- prefix and then removing each remaining dash and changing the letter that follows it to upper case. So data-name-name-name becomes nameNameName.
     
  • You can access the dataset property using the jQuery prop function and then you can access the values using the keys directly as properties. 

jQuery Data

You can use just what has been described so far to work with data in HTML tags but jQuery has a better way. However, it is important to realize that jQuery takes the basic facilities offered by the Dataset API and extends them. In particular jQuery uses its own method of storing the data in an object and not the dataset property.

There are two basic functions .data and .removeData.

The .data function will set and retrieve the data associated with a key:

.data(key,value)

stores the value with the specified key and 

.data(key) 

returns the value associated with the key. jQuery 3 changed the workings of these functions so that they make use of the full Dataset API before this custom attributes were used. What this means is that the .data function makes use of any data-* attributes in the HTML tags to supply initial values. 

However it is important to notice that the data function does not make use of the dataset property to store new values it implements a data storage of its own in a new property added to the object. If the value isn't set in the new property it retrieves it from the dataset property but when you store a new value it doesn't change the dataset property. 

For example with the button still defined as:

<button data-mydata-x="myvalue" 
        data-mydata-y="10" 
        data-mydata-z=20">
test1</button>

you can retreive the values using:

alert($("button").data("mydataX"));
alert($("button").data("mydataY"));
alert($("button").data("mydataZ"));

Notice that we have to use the "camel cased" key names derived from the attributes used in the tag. As well as retrieving values you can also set values:

$("button").data("mydataX","30");

In this case you still use the camel cased key names. The rule is that dashes are used in the tags but not in the JavaScript.

However notice that setting mydataX does not change the dataset property that was created from the tag's attributes. That is:

$("button").data("mydataX","10"); alert($("button").prop("dataset").mydataX);

still displays myvalue and not 10.

You can also pass an object with key value pairs to set a range of key values. Similarly a call to data with no parameters returns an object with key value pairs. In fact it returns the dataset property of the DOM element. For example

alert($("button").data().mydataX);

gives the same result as 

alert($("button").data("mydataX"));

Retrieving all of the data values is faster than getting each one at a time. You can also keep a reference to the object and work with it safely unless you use a .data(obj) call to set all of the values in one go.

jQuery also converts the string values stored in the tag attributes to more appropriate data types - numeric values, true and false etc. 

The removeData function is fairly obvious - it removes data that you previously set but notice that it doesn't remove the attributes from the tags. This means that the next time you do a call to data() you will get the original data as set by the tags i.e. the initial values. For example with the button defined earlier if you do:

$("button").data("mydataX","30").removeData("mydataX"); alert($("button").data("mydataX"));

then you will see the original data value and not 30. That is removeData removes the property that jQuery used to store the value not the property used by the Dataset API.

If you want to remove the data item including from the tag you need to use removeAttr() as well but remember to use the attribute name complete with data- and dashes. For example after:

$("button").data("mydataX","30").
 removeData("mydataX").removeAttr("data-mydata-x");

any attempt to access mydataX after this returns undefined. 

You can remove all of the data changes you have made by calling removeData() and you can also supply a list of keys to be reset as an array. 

This almost all there is to say about data and HTML tags but there are two lower level functions that work with DOM Elements rather than jQuery object. In most cases it is better to work with jQuery object but for completeness we have jQuery.data() and jQuery.removeData(). These work in the same way as data and removeData by you have to specify a DOM element as the first parameter. So for example:

var ele=$("button")[0];
$.data(ele,"mydataX","30");

is the same as  

$("button").data("mydataX","30");

They are used internally by jQuery.



Last Updated ( Thursday, 08 December 2016 )