78

How can a JavaScript array be stored in an HTML custom data attribute?

I've tried every variation of JSON stringification and escaping characters.

What is the precise method to store the array and retrieve it again?

I build the array with [ $("#firstSelectedElement").val(), $("#secondSelectedElement").val() ]. I retrieve id="storageElement" data-storeIt="stuff" with $("#storageElement").data('storeit').

I can never seem to retrieve the data as a true array, only an array of characters.

TylerH
  • 20,799
  • 66
  • 75
  • 101

7 Answers7

97

You could use the HTML escaped characters in the element data attribute to have JSON-like array (encoded are quotes):

<div id="demo" data-stuff='[&#34;some&#34;, &#34;string&#34;, &#34;here&#34;]'></div>

And then in JavaScript get it without any additional magic:

var ar = $('#demo').data('stuff');

See this JSFiddle demo.

However, escaping isn't necessary. You can do this, instead:

<div id="demo" data-stuff='["some", "string", "here"]'></div>

See this JSFiddle demo.

TylerH
  • 20,799
  • 66
  • 75
  • 101
iurii
  • 2,597
  • 22
  • 25
  • 4
    Thanks for the update, It worked. But I don't know why it doesn't works with `data-stuff="['some', 'string', 'here']"` (notice the `'`), any guidance would be appreciated. – Animesh Singh May 20 '17 at 18:40
  • Thanks a million (Y), this is working fine: '["some", "string", "here"]' – Ahmed Mostafa Aug 15 '17 at 09:17
  • 8
    @Animesh Singh : You must use a valid JSON, single quote are not valid JSON. – nand42 Aug 07 '18 at 13:00
  • @nand42 The single quotes issue was what I was encountering. Works like a charm with double quotes! – Chad Mar 05 '19 at 15:33
  • Be aware if there is one item in the data it will result in (int) or (string) value. I wrote an answer how to deal with this. – Henry Feb 13 '20 at 07:55
63

It depends on what type of data you're storing in the array. If it's just strings (as it appears to be) and you have a character that you know will never be a part of your data (like the comma in my example below) then I would forget about JSON serialization and just use string.split:

<div id="storageElement" data-storeIt="stuff,more stuff"></div>

Then when retrieving:

var storedArray = $("#storageElement").data("storeIt").split(",");

It will handle a bit better than using JSON. It uses less characters and is less "expensive" than JSON.parse.

But, if you must, your JSON implementation would look something like this:

<div id="storageElement" data-storeIt='["hello","world"]'></div>

And to retrieve:

var storedArray = JSON.parse($("#storageElement").data("storeIt"));

Notice that in this example we had to use semi-quotes (') around the data-storeIt property. This is because the JSON syntax requires us to use quotes around the strings in its data.

Grinn
  • 5,370
  • 38
  • 51
  • 3
    LOL. I hate it when that happens. I guess a trivial answer that makes you go, "duh!" is better than no solution at all though! – Grinn Apr 25 '13 at 20:32
  • @Gracchus I just noticed that you said you used my suggestion, but didn't mark it as the answer. Did it end up not working out for you? – Grinn May 23 '14 at 16:44
  • For Rails dudes: The JSON version mentioned here is how HAML is dealing with array setting e.g.: `%button{data: {ids: ['a','b','c']} }` => ` – equivalent8 Feb 13 '15 at 16:52
  • @Grinn Do you know why `data-storeIt='["hello","world"]'` works but `data-storeIt="['hello','world']"` doesnt? – dchhetri Nov 08 '16 at 22:48
  • @user814628 Although single quotes are cool in JS, they don't fly in JSON. See this answer for more: http://stackoverflow.com/questions/14355655/jquery-parsejson-single-quote-vs-double-quote – Grinn Nov 14 '16 at 21:31
  • Use of split(",") is the way to go. One other note: You might want to trim each resulting string element, because if your source has spaces after each comma, those spaces will end up in the array elements. Try this: `$("#storageElement").data("storeIt").split(",").map( e => e.trim() );` – Raff Dec 04 '16 at 14:55
  • 1
    It's notable that the solution @Raff suggested uses Arrow Functions which aren't supported in IE < Edge. The equivalent would be `...map(function(s) { return s.trim() })` – Grinn Dec 05 '16 at 14:37
10

The HTML5 data attribute can store only strings, so if you want to store an array you will need to serialize it. JSON will work and it looks like you're on the right path. You just need to use JSON.parse() once you retrieve the serialized data:

var retrieved_string = $("#storageElement").data('storeit');
var retrieved_array = JSON.parse(retrieved_string);

Reviewing the api documentation, jQuery should try to automatically convert a JSON encoded string provided it is properly encoded. Can you give an example of the value you are storing?

Also note that HTML5 data attribute and jQuery .data() methods are two distinct things. They interact, but jQuery is more powerful and can store any data type. You could just store a javascript array directly using jQuery without serializing it. But if you need to have it in the markup itself as an HTML5 data attribute, then you are limited only to strings.

nullability
  • 10,545
  • 3
  • 45
  • 63
3

For the record, it didn't work with encoded entities for me, but seems that in order to be parsed as an object, the data attribute must be a well formed JSON object.

So I was able to use an object with:

data-myarray="{&quot;key&quot;: &quot;value&quot;}"

or maybe just use single quotes:

data-myobject='{"key1": "value1", "key2": value2}'

Time to have fun! :D

Mateo Tibaquira
  • 2,059
  • 22
  • 23
1

You can store any object into node like that:

$('#storageElement').data('my-array', ['a', 'b', 'c']);

var myArray = $('#storageElement').data('my-array');
kayz1
  • 7,260
  • 3
  • 53
  • 56
-1

If you need nested arrays or just another way to do it. This works:

$('[data-example]').each(function (i, e) {
    var json = $(e).data('example');
  for(var index in json){
    console.log(json[index]["name"] + "=" + json[index]["value"]);
  }

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div data-example='[{"name": "A", "value": 1}, {"name": "B", "value": 2}]' />
<div data-example='[{"name": "C", "value": 3}, {"name": "D", "value": 4}]' />

as suggested by Ulysse BN

Or with eval() that is a dangerous solution as pointed by Bonifacius Sarumpaet but works

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div data-example="[['A', 1], ['B', 2]]" />
<div data-example="[['C', 3], ['D', 4]]" />

<script>
  $('[data-example]').each(function (i, e) {
    var arrayFromText = eval($(e).data('example'));
    console.log(arrayFromText[0][0] + "=" + arrayFromText[0][1]);
    console.log(arrayFromText[1][0] + "=" + arrayFromText[1][1]);
  });
</script>
Guilherme Muniz
  • 1,265
  • 11
  • 12
  • what is exactly eval() function in javascript? The only I got online is it executes the argument. – Bonifacius Sarumpaet Nov 09 '20 at 01:50
  • eval(string) will execute the string as code. In this code it is taking the string from data attribute and transforming it in array. You can read more about eval function here: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/eval – Guilherme Muniz Nov 09 '20 at 12:38
  • 2
    I see now. Thanks for the brief explanation. But, from what I read online it is dangerous to put eval() on your code due to its vulnerability to be abused by hacker. – Bonifacius Sarumpaet Nov 10 '20 at 00:22
  • 1
    @BonifaciusSarumpaet you're right, moreover, in most cases eval has really poor performances compared to other solutions (here, `JSON.parse` is much more efficient for instance) – Ulysse BN Nov 16 '20 at 15:48
-3

If using PHP do in PHP:

$arr_test = ['A','C','E'];
$coded = json_encode($arr_test);
// paste coded in data-atribute
print '<div class="funPlus" data-arr_diensten="'. $coded . '"></div>';

The HTML on inspect looks like:

<div class="funPlus" data-arr_diensten="[&quot;A&quot;,&quot;C&quot;,&quot;E&quot;]"></div>

Now in javascript retrieve the array, but if it has only one value it returns as a string. So you have to test and fix this. If it is a string we have to remove the extra quotes. $(this) has to point to the object.

var arr_diensten = $(this).data("arr_diensten");
if (typeof arr_diensten == "string") arr_diensten = [arr_diensten.slice(1, -1)];
console.log(arr_diensten);
Henry
  • 1,242
  • 1
  • 12
  • 10