jQuery .data() does not work, but .attr() does

.attr("data-itemname", "someValue") modifies the DOM.

.data("itemname", "someValue") modifies the jQuery cache.

To get this working in following Javascript and in addition in CSS you have to set both.

theaterA.find(".someLink").attr("data-itemname", "someValue");
theaterA.find(".someLink").data("itemname", "someValue");

This is the result of a misunderstanding: data is NOT an accessor for data-* attributes. It's both more and less than that.

data is an accessor for jQuery's data cache on the element. That cache is initialized from data-* attributes if there are any present, but data never writes to the attributes, nor does changing the attribute change the data cache after initialization:

const div = $("[data-example]");
console.log('div.data("example"):', div.data("example"));
console.log('div.attr("data-example"):', div.attr("data-example"));
console.log('Using div.data("example", "updated")');
div.data("example", "updated");
console.log('div.data("example"):', div.data("example"));
console.log('div.attr("data-example"):', div.attr("data-example"));
<div data-example="initial value"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

data also massages what it finds in various ways, guessing at data types, making data("answer") on an element with data-answer="42" a number, not a string, or even parsing things as JSON if they look like JSON:

console.log(typeof $("[data-answer]").data("answer"));
console.log(typeof $("[data-json]").data("json"));
console.log(typeof $("[data-str]").data("str"));
<div data-answer="42"></div>
<div data-json='{"answer":42}'></div>
<div data-str="example"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

If you want to use the attributes (both reading and setting them), use attr, not data. attr is an accessor for attributes.


I ran into a similar "bug" a few days ago when working with .data() and .attr('data-name') for HTML5 data attributes.

The behavior you're describing is not a bug, but is by design.

The .data() call is special - not only does it retrieve HTML5 data attributes it also attempts to evaluate/parse the attributes. So with an attribute like data-myjson='{"hello":"world"}' when retrieved via .data() will return an Object while retrieval via .attr() will return a string. See jsfiddle example.

Since .data() does extra processing jQuery stores the results of attribute evaluation in $.cache - after all, once a data attribute has been evaluated it would be wasteful to re-evaluate on every .data() call - especially since data variables can contain complex JSON strings.

I said all that to say the following: After retrieving an attribute via .data() any changes made by .attr('data-myvar', '') will not be seen by subsequent .data() calls. Test this out on jsfiddle.

To avoid this problem don't intermix .data and .attr() calls. Use one or the other.

Tags:

Jquery