99

Although there are some examples of this on the web, it does not seem to work correctly. I can't figure out the problem.

I have this simple HTML

<div id="foo" data-num="0"></ div>
<a href="#" id="changeData">change data value</a>

Every time I click the link "change data value" I want to update the data value of data-num. For example, I need it to be 1,2,3,4,... (plus 1 every time I click the link)

what I have is

var num = $('#foo').data("num");
console.log(num);
num = num+1;               
console.log(num);
$('#foo').attr('data-num', num);   

The value changes one time from 0 to 1 every time. I can't make it incremental. Any suggestions on what I'm doing wrong?

Mukesh Panchal
  • 1,956
  • 2
  • 18
  • 31
dev
  • 1,377
  • 1
  • 10
  • 28
  • 6
    data- is only an attribute on page load. Data is loaded into the dom and manipulated there using `.data()`. The attribute is not updated and should not be used to store or retrieve data, only to initially set data. –  Nov 13 '13 at 12:21
  • 1
    @NigelAngel Wrong. The purpose of the data attribute is to provide a means by which users can store (and modify) arbitrary data that does not have any other valid place to go. And example of this would be for foreign currency when the decimal point is a comma. To numerical calculations with this you have to store a proper value with an actual decimal point somewhere. If this is a total price and needs to be updated based on changes then again this data value would have to change and therefore you need to be able to update it. For this, you would use the .attr() – jezzipin Oct 23 '15 at 15:38

9 Answers9

126

Use that instead, if you wish to change the attribute data-num of node element, not of data object:

DEMO

$('#changeData').click(function (e) { 
    e.preventDefault();
    var num = +$('#foo').attr("data-num");
    console.log(num);
    num = num + 1;
    console.log(num);
    $('#foo').attr('data-num', num);
});

PS: but you should use the data() object in virtually all cases, but not all...

A. Wolff
  • 74,033
  • 9
  • 94
  • 155
  • 7
    Data is loaded into the dom and manipulated there using .data(). The attribute is not updated and should not be used to store or retrieve data, only to initially set data. While this is one way to change an attribute (`.prop()` is preferred), it is not the correct way to use data. –  Nov 13 '13 at 12:23
  • @NigelAngel When `.prop()` should be used to set data attribute, i don't get it? BTW you are correct, usually `data()` must be used but sometimes you need to update the attribute set in DOM to fit e.g some CSS rules, then here, `attr()` must be used (not `.prop()` nor `.data()`). – A. Wolff May 07 '14 at 09:40
  • ↑↑↑ That's said, using `data-*` attribute to set some specific style is not the best way but i had already to deal with this kind of thing for some plugins (cannot remember which ones actually) – A. Wolff May 07 '14 at 09:48
  • @AWolff `.prop()` or `.attr()` may be used for attributes. –  May 07 '14 at 12:06
  • @NigelAngel `.prop()` set the property of DOM node, not the attribute nor data object property: http://jsfiddle.net/eXA76/ If i don't undertand your previous comment, could you elaborate? – A. Wolff May 07 '14 at 12:14
  • 4
    `.prop()` will access or alter the value of any property or attribute in the DOM but not the HTML. `.attr()` will access and rewrite HTML which makes it slower than `.prop()`. You shouldn't use `.attr()` instead of `.data()`, not just because it's slower, but because that's not how it's supposed to work. http://jsfiddle.net/eXA76/2/ –  May 07 '14 at 17:53
  • @NigelAngel So indeed we're agree, at least, I'm agree with you... ;) – A. Wolff May 07 '14 at 17:56
  • 1
    I think this answer should be deleted because it gives bad advice on using data(). –  May 07 '14 at 17:59
  • 1
    @NigelAngel `Use that instead, if you wish to change the attribute data-num of node element, not of data object` which was answering question as asked before OP realized he was asking it wrong. Now some other guys could have same issue but still need to update the attribute, not the property, nothing wrong here – A. Wolff May 08 '14 at 08:24
  • @NigelAngel & downvoter Sorry to answer question as asked... This answer doesn't gives bad advice on using `data()`, it gives answer how to set data attribute, not property or data object. All comments here were to get explaination about your comment `While this is one way to change an attribute (.prop() is preferred)` How can prop() be better to set attribute in DOM??? – A. Wolff May 09 '14 at 12:23
  • @NigelAngel Can you provide some reference to `attribute is not updated and **should not be used** to store or retrieve data`? What's wrong with using attribute to store or retrieve data? (other than it being slow because it rewrites HTML) – user Jul 19 '14 at 07:06
  • 2
    Yes, the jQuery docs on how it's supposed to be used! http://api.jquery.com/data/ data is stored in a global variable on document load. Referencing it via the attribute WILL NOT WORK if another developer, plugin or script **correctly** updates the data using `.data()`. By ignoring the correct method and using the attribute you are heading towards knowingly causing problems. –  Jul 19 '14 at 12:12
  • 4
    @NigelAngel Whilst I appreciate your opinion on this, data is not always the best option to use. What if you need to update the value of a data attribute and have it displayed in the dom as well as actually changing the underlying value that is then used by CSS or even Javascript? The best approach is typically to use .data() if you are not updating the value in any way from Javascript but if you are, always use .attr() to both set and retrieve the value. – jezzipin Oct 23 '15 at 15:33
65

THE ANSWER BELOW IS THE GOOD ONE

You aren't using the data method correctly. The correct code to update data is:

$('#foo').data('num', num); 

So your example would be:

var num = $('#foo').data("num") + 1;       
console.log(num)       
$('#foo').data('num', num); 
console.log(num)
Lucas Willems
  • 6,673
  • 4
  • 28
  • 45
  • 106
    This is wrong, this is the ***wrong*** method to update an attribute – adeneo Jul 20 '13 at 13:54
  • 2
    Yes I agree with you @adeneo but he is not using the data method correctly. Why use this kind of attribute if you want to update it with the attr method ? – Lucas Willems Jul 20 '13 at 13:56
  • @dev i edited my answer and add the whole code you have to use. – Lucas Willems Jul 20 '13 at 13:58
  • I removed "attribute". – Lucas Willems Jul 20 '13 at 14:00
  • 8
    This is interesting. I can see that the value changes in the console. But when I look at the html using Chrome it is 0 (initial). I guess it is ok if later on I can retrieve the last value (for example 5) – dev Jul 20 '13 at 14:04
  • @dev this is how it is expected to work. If you want to change the ATTRIBUTE, see my answer – A. Wolff Jul 20 '13 at 14:05
  • 6
    As @dev said i tried and saw that's changed in jQuery but not affect html in chrome and safari. So i decide to use attr() rather data(). – QMaster Jul 28 '14 at 13:03
  • I found that a number such as 180200000029757103 gets changed if I use data method to retrieve value. When using attr the number get returned as string but is not altered at least – Dmitry Jun 08 '17 at 20:31
  • works only on page load, but when data attribute changed dynamically, next time on data fetch old value is fetched. on using $('#foo').attr('data-num', num) this query valued fetched correctly – Tamilselvan K May 11 '18 at 01:42
  • This will work only for the very first time, we wont be able to change the value afterwards.Once set, it wont change using this logic. – Alisha Raju Dec 21 '18 at 05:09
  • there was a good explanation about this on [the other StackOverflow discussion](https://stackoverflow.com/a/29907463). – Andang Rian Dimas Apr 21 '20 at 02:15
34

If we wanted to retrieve or update these attributes using existing, native JavaScript, then we can do so using the getAttribute and setAttribute methods as shown below:

JavaScript

<script>
// 'Getting' data-attributes using getAttribute
var plant = document.getElementById('strawberry-plant');
var fruitCount = plant.getAttribute('data-fruit'); // fruitCount = '12'

// 'Setting' data-attributes using setAttribute
plant.setAttribute('data-fruit','7'); // Pesky birds
</script>

Through jQuery

// Fetching data
var fruitCount = $(this).data('fruit');

// Above does not work in firefox. So use below to get attribute value.
var fruitCount = $(this).attr('data-fruit');

// Assigning data
$(this).data('fruit','7');

// But when you get the value again, it will return old value. 
// You have to set it as below to update value. Then you will get updated value.
$(this).attr('data-fruit','7'); 

Read this documentation for vanilla js or this documentation for jquery

Lalit Kumar Maurya
  • 5,475
  • 2
  • 35
  • 29
  • @Nigel Angel, Have you tested it on firefox? $(this).data('fruit') does not work on firefox. – Lalit Kumar Maurya Oct 28 '15 at 06:24
  • Thank you very much for last advice "You have to set it as below to update value. Then you will get updated value" rly strange behaviour in jquery.. – jgr Mar 07 '16 at 13:39
17

For myself, using Jquery lib 2.1.1 the following did NOT work the way I expected:

Set element data attribute value:

$('.my-class').data('num', 'myValue');
console.log($('#myElem').data('num'));// as expected = 'myValue'

BUT the element itself remains without the attribute:

<div class="my-class"></div>

I needed the DOM updated so I could later do $('.my-class[data-num="myValue"]') //current length is 0

So I had to do

$('.my-class').attr('data-num', 'myValue');

To get the DOM to update:

<div class="my-class" data-num="myValue"></div>

Whether the attribute exists or not $.attr will overwrite.

StealthRT
  • 10,108
  • 40
  • 183
  • 342
Brian Ogden
  • 18,439
  • 10
  • 97
  • 176
9

Had similar problem and in the end I had to set both

obj.attr('data-myvar','myval')

and

obj.data('myvar','myval')

And after this

obj.data('myvar') == obj.attr('data-myvar')

Hope this helps.

noufalcep
  • 3,446
  • 15
  • 33
  • 51
Krist0K
  • 111
  • 1
  • 2
9

Basically, there are two ways to set / update data attribute value, depends on your need. The difference is just, where the data saved,

If you use .data() it will be saved in local variable called data_user, and its not visible upon element inspection, If you use .attr() it will be publicly visible.

Much clearer explanation on this comment

  • The fact that the values are stored by Jquery in a way that can only be accessed locally is an advantage when using .data () to manage dynamic values in the page, avoiding the problem that they can be modified by the browser inspector. – Lorenzo Magon Jul 12 '22 at 06:49
2

This answer is for those seeking to just change the value of a data-attribute

The suggested will not change the value of your Jquery data-attr correctly as @adeneo has stated. For some reason though, I'm not seeing him (or any others) post the correct method for those seeking to update their data-attr. The answer that @Lucas Willems has posted may be the answer to problem Brian Tompsett - 汤莱恩 is having, but it's not the answer to the inquiry that may be bringing other users here.

Quick answer in regards to original inquiry statement

-To update data-attr

$('#ElementId').attr('data-attributeTitle',newAttributeValue);

Easy mistakes* - there must be "data-" at the beginning of your attribute you're looking to change the value of.

MattOlivos
  • 221
  • 2
  • 7
2

Had a similar problem, I propose this solution althought is not supported in IE 10 and under.

Given

<div id='example' data-example-update='1'></div>

The Javascript standard defines a property called dataset to update data-example-update.

document.getElementById('example').dataset.exampleUpdate = 2;

Note: use camel case notation to access the correct data attribute.

Source: https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes

Giovanni Romio
  • 1,008
  • 1
  • 11
  • 30
2

I had the same problem of the html data tag not updating when i was using jquery But changing the code that does the actual work from jquery to javascript worked.

Try using this when the button is clicked: (Note that the main code is Javascripts setAttribute() function.)

function increment(q) {

    //increment current num by adding with 1
    q = q+1;

    //change data attribute using JS setAttribute function
    div.setAttribute('data-num',q);

    //refresh data-num value (get data-num value again using JS getAttribute function)
    num = parseInt(div.getAttribute('data-num'));

    //show values
    console.log("(After Increment) Current Num: "+num);

}

//get variables, set as global vars
var div = document.getElementById('foo');
var num = parseInt(div.getAttribute('data-num'));

//increment values using click
$("#changeData").on('click',function(){

    //pass current data-num as parameter
    increment(num);

});
Gash
  • 81
  • 4