34

I'm playing around with the attr-data-* attributes of HTML5 and the corresponding javascript dataset

I'm doing alot of dynamic form processing, so I end up getting stuff like this:

<input data-feaux="bar" data-fizz="buzz"/>

Since HTMLElement.dataset returns a DOM string map, the only way I can figure out how to convert it into an native object is:

var obj = JSON.parse(JSON.stringify(input_el.dataset))

Is there a better way to do this?

Edit:

Why would I want to do this? Let's say I have many, many of these elements. I want to loop through them all and push them into an array for processing later, i.e.

elements = document.querySelectorAll("input")
my_data_array = []
for(var i = 0; i < elements.length; i++) {
    my_data_array.push(elements[i].dataset)
}

Now I have an array of objects, i.e. [{feaux: "bar", fizz:"buzz"}....] that I can work with.

However, when I don't convert the DOM string map into an object, the array doesn't get populated (i.e. the code above doesn't work)

Edit 2

Looking closer, it is actually a DOM string map, not an object. Correcting typos in the original question to reflect this.

CamelBlues
  • 3,444
  • 5
  • 29
  • 37
  • It already is an object. Why do you want it to be native? – cookie monster May 16 '14 at 19:30
  • 1
    @cookiemonster because `DOM string object` doesn't like being pushed into an array and I loose the keys; I've edited my question to give an example – CamelBlues May 30 '14 at 19:29
  • In what browser does that not work? Works fine for me in Firefox. ...works in Chrome too. – cookie monster May 30 '14 at 20:04
  • ...anyway, if you wanted to store the `dataset` objects, you might as well store the elements themselves since storing the `dataset` is going to retain a reference to the element since the `dataset` relies on the element to work. – cookie monster May 30 '14 at 20:06
  • @cookiemonster yeah, I can get this to work in the console of Chrome, but some reason loading it from a script file or running it with a headless web browser, the `DOM string maps` don't go into the array correctly. I'm going to be doing more testing; this could be a bug higher up in the line :P – CamelBlues May 30 '14 at 20:38

4 Answers4

44

You can use Object.assign

Object.assign({}, element.dataset) 

For browsers that doesn't support Object.assign you can use polyfill

Agung Prasetyo
  • 4,353
  • 5
  • 29
  • 37
10

in es6 you can use the object spread.
{ ...element.dataset }

PhilWilliammee
  • 541
  • 6
  • 10
9

Don't forget about JSON.stringify and JSON.parse.

var data = document.getElementById('someElement').dataset;
data = JSON.parse(JSON.stringify(data));

According to Mozilla this should work all the way back to IE 8 without a polyfill.

Collin Craige
  • 109
  • 1
  • 8
2

Here's a little function to retrieve the element dataset as a normal object:

function datasetToObject(elem){
    var data = {};
    [].forEach.call(elem.attributes, function(attr) {
        if (/^data-/.test(attr.name)) {
            var camelCaseName = attr.name.substr(5).replace(/-(.)/g, function ($0, $1) {
                return $1.toUpperCase();
            });
            data[camelCaseName] = attr.value;
        }
    });
    return data;
}

Scooped up from: Get list of data-* attributes using javascript / jQuery

Community
  • 1
  • 1
bob
  • 7,539
  • 2
  • 46
  • 42