334

I have a div with an attribute data-myval = "10". I want to update its value; wouldn't it change if I use div.data('myval',20)? Do I need to use div.attr('data-myval','20') only?

Am I getting confused between HTML5 and jQuery? Please advise. Thanks!

EDIT: Updated div.data('myval')=20 to div.data('myval',20), but still the HTML is not updating.

Pulkit Mittal
  • 5,916
  • 5
  • 21
  • 28
  • 2
    What is in `div`? A jQuery object or element? – Brad Nov 23 '12 at 06:31
  • 2
    `div.data('myval')=20` wouldn't work to store a value only because the syntax is wrong - see the answers for the correct syntax. But note that `.data()` doesn't actually update the element _attribute,_ it stores the data elsewhere. – nnnnnn Nov 23 '12 at 06:40
  • For those who has the sense to avoid gQuery use this -> div.dataset.myval = '20'; – Harijs Krūtainis Jun 09 '20 at 13:00

7 Answers7

634

HTML

<div id="mydiv" data-myval="10"></div>

JS

var a = $('#mydiv').data('myval'); //getter

$('#mydiv').data('myval',20); //setter

Demo

Reference

From the reference:

jQuery itself uses the .data() method to save information under the names 'events' and 'handle', and also reserves any data name starting with an underscore ('_') for internal use.

It should be noted that jQuery's data() doesn't change the data attribute in HTML.

So, if you need to change the data attribute in HTML, you should use .attr() instead.

HTML

<div id="outer">
    <div id="mydiv" data-myval="10"></div>
</div>

​jQuery:

alert($('#outer').html());   // alerts <div id="mydiv" data-myval="10"> </div>
var a = $('#mydiv').data('myval'); //getter
$('#mydiv').attr("data-myval","20"); //setter
alert($('#outer').html());   //alerts <div id="mydiv" data-myval="20"> </div>

See this demo

Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
Jashwant
  • 28,410
  • 16
  • 70
  • 105
  • 1
    I dont know what consistency you need, but I would recommend to use `data()` to `get` and `set` HTML-5 data attributes. – Jashwant Nov 23 '12 at 07:23
  • 7
    @Jashwant might be a useful edit instead: think of a css rule like `[data-myval="10"]{ color: red; }`, it would style the tag according to value of data attribute. – Niki Romagnoli Jun 28 '17 at 12:24
  • 8
    .data doesn't work. .attr works. may be we can edit the answer to make it clear. it seems the first one is the solution, while it could be a little bit better exposed. i'm not sure about how to better explain, this is the reason why I don't edit the post. – Gaucho Nov 02 '18 at 11:58
  • @Gaucho, is it better now ? – Jashwant Nov 02 '18 at 15:16
  • 2
    @Gaucho .data will only work if you use newer jQuery >= 1.4.3, for older versions .attr will work. – Ilias Nov 15 '18 at 17:02
  • Still here, wondering why we have both a data object and a data attribute, and wondering why they aren't kept in sync. – brandonscript Jun 19 '20 at 06:03
  • @brandonscript, (I may not be correct) jQuery introduced `data()` before HTML `data-` attributes. So, it used to store data internally in objects. – Jashwant Jun 19 '20 at 11:53
  • >> Using the data() method to update data does not affect attributes in the DOM. To set a data-* attribute value, use attr. https://api.jquery.com/data/ – Franchy Jun 22 '21 at 17:41
64

Vanilla Javascript solution

HTML

<div id="mydiv" data-myval="10"></div>

JavaScript:

  • Using DOM's getAttribute() property

     var brand = mydiv.getAttribute("data-myval")//returns "10"
     mydiv.setAttribute("data-myval", "20")      //changes "data-myval" to "20"
     mydiv.removeAttribute("data-myval")         //removes "data-myval" attribute entirely
    
  • Using JavaScript's dataset property

    var myval = mydiv.dataset.myval     //returns "10"
    mydiv.dataset.myval = '20'          //changes "data-myval" to "20"
    mydiv.dataset.myval = null          //removes "data-myval" attribute
    
RiZKiT
  • 2,107
  • 28
  • 23
rajesh kakawat
  • 10,826
  • 1
  • 21
  • 40
56

You can also use the following attr thing;

HTML

<div id="mydiv" data-myval="JohnCena"></div>

Script

 $('#mydiv').attr('data-myval', 'Undertaker'); // sets 
 $('#mydiv').attr('data-myval'); // gets

OR

$('#mydiv').data('myval'); // gets value
$('#mydiv').data('myval','John Cena'); // sets value
Baqer Naqvi
  • 6,011
  • 3
  • 50
  • 68
  • 11
    For me worked only with .attr. Is that even possible? – Zariweya Aug 21 '17 at 15:03
  • 1
    I am glad it worked. 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-myval='{"hello":"world"}' when retrieved via .data() will return an Object while retrieval via .attr() will return a string. – Baqer Naqvi Aug 21 '17 at 18:00
35

Please take note that jQuery .data() is not updated when you change html5 data- attributes with javascript.

If you use jQuery .data() to set data- attributes in HTML elements you better use jQuery .data() to read them. Otherwise there can be inconsistencies if you update the attributes dynamically. For example, see setAttribute(), dataset(), attr() below. Change the value, push the button several times and see the console.

$("#button").on("click", function() {
  var field = document.querySelector("#textfield")

  switch ($("#method").val()) {
    case "setAttribute":
      field.setAttribute("data-customval", field.value)
      break;
    case "dataset":
      field.dataset.customval = field.value
      break;
    case "jQuerydata":
      $(field).data("customval", field.value)
      break;
    case "jQueryattr":
      $(field).attr("data-customval", field.value)
      break;
  }

  objValues = {}
  objValues['$(field).data("customval")'] = $(field).data("customval")
  objValues['$(field).attr("data-customval")'] = $(field).attr("data-customval")
  objValues['field.getAttribute("data-customval")'] = field.getAttribute("data-customval")
  objValues['field.dataset.customval'] = field.dataset.customval

  console.table([objValues])
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<h1>Example</h1>
<form>
  <input id="textfield" type="text" data-customval="initial">
  <br/>
  <input type="button" value="Set and show in console.table (F12)" id="button">
  <br/>
  <select id="method">
    <option value="setAttribute">setAttribute</option>
    <option value="dataset">dataset</option>
    <option value="jQuerydata">jQuery data</option>
    <option value="jQueryattr">jQuery attr</option>
  </select>
  <div id="results"></div>
</form>
Kirby
  • 15,127
  • 10
  • 89
  • 104
Johann Echavarria
  • 9,695
  • 4
  • 26
  • 32
16

To keep jQuery and the DOM in sync, a simple option may be

$('#mydiv').data('myval',20).attr('data-myval',20);        
BEingprabhU
  • 1,618
  • 2
  • 21
  • 28
J. McNerney
  • 576
  • 4
  • 15
10

If you're using jQuery, use .data():

div.data('myval', 20);

You can store arbitrary data with .data(), but you're restricted to just strings when using .attr().

Blender
  • 289,723
  • 53
  • 439
  • 496
  • 15
    Note that the `.data()` method does _not_ update `data-` _attributes_ - that is, the data it stores does not end up in an attribute (which is why it can store non-string values) even though it can retrieve the value from a `data-` attribute. Though I suspect the OP doesn't really need to set _attributes_ even though that's what the question asked. – nnnnnn Nov 23 '12 at 06:37
  • @nnnnnn: I'm not too sure when that'd end up being a problem outside of looking at the `data-` attribute through Chrome's Inspector or Firebug. – Blender Nov 23 '12 at 06:41
  • 1
    I don't think it would be a problem (besides what you mentioned, or if there is other code that uses `.attr()` to retrieve the attribute). I just thought it was worth pointing out given that the OP explicitly (if perhaps mistakenly) asked about updating attributes. – nnnnnn Nov 23 '12 at 06:43
  • 1
    @Blender this doesn't really answer my question. I want to update the HTML, but at the same time, use element.data('myval') to retrieve it as well. – Pulkit Mittal Nov 23 '12 at 06:58
  • @PulkitMittal: Read @nnnnnn's comments. `.data('foo', 12)` is not the same as `.attr('data-foo', '12')`. Why do you need to update the HTML? – Blender Nov 23 '12 at 07:00
  • 1
    I need to do that because the elements generated on document load have those as data-attributes, and I want to do so for the new dynamic elements as well. I know there might be not a specific need for that, but I want to keep a consistency. – Pulkit Mittal Nov 23 '12 at 07:12
  • @PulkitMittal: But why? If you're going to be accessing the data attributes with `data()`, there's no use in changing the DOM element like that. – Blender Nov 23 '12 at 07:13
  • I guess. hmm... Then I think I can change both, using `.attr()` and `.data()` to keep the consistency. – Pulkit Mittal Nov 23 '12 at 07:16
  • @PulkitMittal: I'm still not understanding why you need to do this. It's pointless. – Blender Nov 23 '12 at 07:17
  • TO KEEP THE CONSISTENCY. I told you so! – Pulkit Mittal Nov 23 '12 at 07:18
  • @PulkitMittal: I'm not going to argue about it. I'm just pointing out that there is no reason to do this and you're wasting your time trying. – Blender Nov 23 '12 at 07:23
  • Thanks for your input @Blender; I appreciate it. I will keep both setters, just in case any of my later Javascript uses data-attr or something. – Pulkit Mittal Nov 23 '12 at 07:41
  • 1
    @PulkitMittal - Note that even with `.attr()` you're not really updating "the html", you're updating the DOM. When you ask the browser to give you the "html" (whether by `.html()` or the DOM `element.innerHTML`) the browser is effectively regenerating it for you based on the state of the DOM at the time. Sort of. – nnnnnn Nov 23 '12 at 07:52
  • 1
    @nnnnnn that's the most important part of how the `.data()` method works. Thanks for pointing that out! – MrUpsidown Mar 25 '15 at 09:20
8

[jQuery] .data() vs .attr() vs .extend()

The jQuery method .data() updates an internal object managed by jQuery through the use of the method, if I'm correct.

If you'd like to update your data-attributes with some spread, use --

$('body').attr({ 'data-test': 'text' });

-- otherwise, $('body').attr('data-test', 'text'); will work just fine.

Another way you could accomplish this is using --

$.extend( $('body')[0].dataset, { datum: true } );

-- which restricts any attribute change to HTMLElement.prototype.dataset, not any additional HTMLElement.prototype.attributes.

Cody
  • 9,785
  • 4
  • 61
  • 46