How to set data attributes in HTML elements
Asked Answered
L

8

339

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.

Laurynlausanne answered 23/11, 2012 at 6:29 Comment(4)
What is in div? A jQuery object or element?Graybeard
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.Fluorene
For those who has the sense to avoid gQuery use this -> div.dataset.myval = '20';Pew
I feel bad saying this, but IMHO, users should completely ignore the highest voted answer and read one of the others. After over an hour of troubleshooting why data() didn't work as expected (for the nth time in my career), I finally decided to get to the bottom of it. I documented my findings in my own answer, but to summarize, data probably doesn't work the way you expect. attr probably does work the way you expect. Use attr.Fala
O
647

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

Obstinate answered 23/11, 2012 at 6:32 Comment(9)
I dont know what consistency you need, but I would recommend to use data() to get and set HTML-5 data attributes.Obstinate
@Obstinate 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.Shuster
.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.Mousterian
@Gaucho, is it better now ?Obstinate
@Mousterian .data will only work if you use newer jQuery >= 1.4.3, for older versions .attr will work.Wichern
Still here, wondering why we have both a data object and a data attribute, and wondering why they aren't kept in sync.Chemistry
@brandonscript, (I may not be correct) jQuery introduced data() before HTML data- attributes. So, it used to store data internally in objects.Obstinate
>> Using the data() method to update data does not affect attributes in the DOM. To set a data-* attribute value, use attr. api.jquery.com/dataYellow
I feel bad saying this, but IMHO, users should completely ignore this answer and read one of the others. After over an hour of troubleshooting why data() didn't work as expected (for the nth time in my career), I finally decided to get to the bottom of it. I documented my findings in my own answer, but to summarize, data probably doesn't work the way you expect. attr probably does work the way you expect. Use attr.Fala
G
65

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
    
Gerladina answered 23/11, 2012 at 7:47 Comment(0)
B
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
Byrom answered 16/8, 2016 at 17:12 Comment(2)
For me worked only with .attr. Is that even possible?Showplace
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.Byrom
J
36

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>
Jumbo answered 24/9, 2014 at 17:25 Comment(3)
I feel like I should know this, but how do you know if you are using html5 data- attributes?Fala
@DanielKaplan when you use a data- attribute in the HTML developer.mozilla.org/en-US/docs/Learn/HTML/Howto/…Jumbo
So a non-html5 data- attribute does not exist. Gotcha.Fala
A
18

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

$('#mydiv').data('myval',20).attr('data-myval',20);        
Afc answered 29/1, 2020 at 15:2 Comment(1)
$('#mydiv').attr('data-myval',20); this working wellBuyer
S
8

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().

Sokol answered 23/11, 2012 at 6:31 Comment(14)
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.Fluorene
@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.Sokol
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.Fluorene
@Sokol 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.Laurynlausanne
@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?Sokol
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.Laurynlausanne
@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.Sokol
I guess. hmm... Then I think I can change both, using .attr() and .data() to keep the consistency.Laurynlausanne
@PulkitMittal: I'm still not understanding why you need to do this. It's pointless.Sokol
TO KEEP THE CONSISTENCY. I told you so!Laurynlausanne
@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.Sokol
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.Laurynlausanne
@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.Fluorene
@Fluorene that's the most important part of how the .data() method works. Thanks for pointing that out!Jeanene
S
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.

Slobber answered 17/12, 2017 at 7:38 Comment(0)
F
0

TL;DR: div.attr('data-myval', 20)


Depending on your needs and your jQuery version, the highest voted answer might work, but you are better off using attr(`data-myval`)/attr(`data-myval`, newVal). As you'll see by running the following snippet, attr works as exactly the way you'd expect:

jQuery attr() test

let $div = $(`#jquery-3-7-1`);
console.log(`Using attr() in jquery 3.7.1`);
console.log("\t$div.attr(`data-myval`) =", $div.attr(`data-myval`));
console.log("  Running $div.attr(`data-myval`, '20');")
$div.attr(`data-myval`, '20');
console.log("\t$div.attr(`data-myval`) =", $div.attr(`data-myval`));
console.log("  HTML =", $div[0].outerHTML);
console.log(`\n`);
$.noConflict(true);

$div = $(`#jquery-1-4-3`);
console.log(`Using attr() in jquery 1.4.3`);
console.log("\t$div.attr(`data-myval`) =", $div.attr(`data-myval`));
console.log("  Running $div.attr(`data-myval`, '20');")
$div.attr(`data-myval`, '20');
console.log("\t$div.attr(`data-myval`) =", $div.attr(`data-myval`));
console.log("  HTML =", $div[0].outerHTML);
console.log(`\n`);
$.noConflict(true);

$div = $(`#jquery-1-4-2`);
console.log(`Using attr() in jquery 1.4.2`);
console.log("\t$div.attr(`data-myval`) =", $div.attr(`data-myval`));
console.log("  Running $div.attr(`data-myval`, '20');")
$div.attr(`data-myval`, '20');
console.log("\t$div.attr(`data-myval`) =", $div.attr(`data-myval`));
console.log("  HTML =", $div[0].outerHTML);
console.log(`\n`);
$.noConflict(true);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<div id="jquery-1-4-2" data-myval="10"></div>
<div id="jquery-1-4-3" data-myval="10"></div>
<div id="jquery-3-7-1" data-myval="10"></div>

jQuery data() test

data(...), on the other hand, probably doesn't do what you want:

  1. The data(`myval`, val) setter does not modify the HTML.
  2. In jQuery <= 1.4.2, the data(`myval`) getter ignores HTML attributes.

let $div = $(`#jquery-3-7-1`);
console.log(`Using data() in jquery 3.7.1`);
console.log("\t$div.data(`myval`) =", $div.data(`myval`));
console.log("  Running $div.data(`myval`, '20');")
$div.data(`myval`, '20');
console.log("\t$div.data(`myval`) =", $div.data(`myval`));
console.log("  HTML =", $div[0].outerHTML, `<-------- !!!`);
console.log(`\n`);
$.noConflict(true);

$div = $(`#jquery-1-4-3`);
console.log(`Using data() in jquery 1.4.3`);
console.log("\t$div.data(`myval`) =", $div.data(`myval`));
console.log("  Running $div.data(`myval`, '20');")
$div.data(`myval`, '20');
console.log("\t$div.data(`myval`) =", $div.data(`myval`));
console.log("  HTML =", $div[0].outerHTML, `<-------- !!!`);
console.log(`\n`);
$.noConflict(true);

$div = $(`#jquery-1-4-2`);
console.log(`Using data() in jquery 1.4.2`);
console.log("\t$div.data(`myval`) =", $div.data(`myval`), `<-------- !!!`);
console.log("  Running $div.data(`myval`, '20');")
$div.data(`myval`, '20');
console.log("\t$div.data(`myval`) =", $div.data(`myval`));
console.log("  HTML =", $div[0].outerHTML, `<-------- !!!`);
console.log(`\n`);
$.noConflict(true);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<div id="jquery-1-4-2" data-myval="10"></div>
<div id="jquery-1-4-3" data-myval="10"></div>
<div id="jquery-3-7-1" data-myval="10"></div>

This comment on the highest voted answer gives an explanation as to why, but I haven't confirmed it to be historically accurate.

In summary, use attr instead of data.

Fala answered 7/4 at 7:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.