Data attribute with JavaScript and jQuery

Acessing data attributes with JavaScript and jQuery By Yihang Ho

One thing from HTML5 that fascinates me a lot is the data- attribute. It helps eliminating some clumsiness that happen before HTML5 especially when writing a single-page application. For example, sometimes we need to use a hidden input to store some temporary states. Those data can be stored in the data- attribute.

<form>
    <input type="hidden" name="user-id" value="12345">
    <input type="text" name="fname">
</form>

can be replaced with

<form data-user-id="12345">
    <input type="text" name="fname">
</form>

Another advantage of data- attribute is the ability to write unobtrusive JavaScript. If you have seen the HTML code generated by Ruby on Rails, you will understand. Suppose you want to show the user a confirmation box after the user clicked on a link. Without the data- attribute, we have to do this

<a href="http://www.example.com" onclick="return confirm('Are you sure?');">Click me!</a>

which is kind of not nice as we have to inline some JavaScript code. With data- attribute, however, we can do this

<!-- index.html -->
<a href="http://www.example.com" data-confirmation="Are you sure?">Click me!</a>
<script src="script.js"></script>
// script.js
var anchors = document.getElementsByTagName("a");
for (var i = 0; i < anchors.length; i++) {
    anchors[i].onclick = anchorOnClickListener;
}
function anchorOnClickListener() {
    return this.dataset.confirmation ? confirm(this.dataset.confirmation) : true;
}

As we can see, although the second method results in a much longer code, we will also enjoy all the benefits that come with writing obtrusive JavaScript.

Our beloved jQuery, as expected, handles data- attributes gracefully. There is a dedicated method to do this - .data(). In the first example, we can retrieve the data-user-id attribute with

$("form").data("user-id");

Updating data- attributes can be done in a similar fashion:

$("form").data("user-id", "new-user-id");

However, if you try to inspect the element that you have just updated its data- attribute, you might notice that the old value is still there. In this case, data-user-id is still 12345 instead of new-user-id. It turns out that jQuery do not update data- attributes directly, instead, the new or updated value is stored in a cache variable and is associated with the DOM of the said element. To verify this, use the developer's console and set then retrieve the data- attribute.

<!-- Insert this part in a HTML file -->
<div id="demo-div" data-number="1"></div>

and enter these into the console, one line after the other

$("div#demo-div").data("number"); //You should get 1
$("div#demo-div").data("number", 2); //Check the HTML after entering this line to verify that data-number still appears to be 1
$("div#demo-div").data("number"); //You should get 2

So what is the impact of the way jQuery is handling data- attributes? First of all, you cannot access updated data- attribute using non-jQuery JavaScript. Continuing the previous example,

$("div#demo-div").data("number", 2); //Just to make sure it is re-updated using jQuery
document.getElementById("demo-div").dataset.number; //You will still get 1

But the other way works, that it, jQuery can access data- attributes updated by non-jQuery JavaScript.

$("div#demo-div").data("number", 2); //Re-update with jQuery
document.getElementById("demo-div").dataset.number = 3; //Update with non-jQuery JavaScript
$("div#demo-div").data("number"); //Expect 3

By using the jQuery .data() method, you can set any data- attributes to almost anything, including arrays and objects:

$("div#demo-div").data("another", { hello: "World" });

In most cases, the behavior of jQuery shouldn't be a very big issue. In case it really is, just remember that there is the faithful .attr() method.

$("div#demo-div").attr("data-number", 10); //Verify that HTML is being updated also
document.getElementById("demo-div").dataset.number; //Expect 10