Since HTML data
attribute allows adding any custom data, I wonder if it is a good idea to include a set of JSON
list as a data
attribute?
Technically you can, and I have seen several sites do this, but another solution is to store your JSON in a <script>
tag and put a reference to the script tag in the data
attribute. This is a better solution than just storing the data as a JS object in an actual script if the data is rendered to the page server-side, but there are CSP restrictions on inline script tags, for example.
HTML
<div data-data-id="#MyScriptData" id="x"></div>
<script type="application/json" id="MyScriptData">
{
"fruit": "apple",
...
}
</script>
JS
$(function () {
var dataId = $("#x").data("data-id");
var dataTag = $(dataId);
var dataJson = dataTag.html(); // returns a string containing the JSON data
var data = JSON.parse(dataJson);
...
});
Say you want to save the object var dataObj = { foo: 'something', bar: 'something else' };
to an html data attribute.
Consider first stringifying the object such that we have
var stringifiedDataObj = JSON.stringify(dataObj);
Then you can use jQuery to set the stringifiedDataObj as the data attribute e.g. with the jQuery.data()
API
Instead of storing everything in the data attribute you could use an identifier to access the data.
So for example you could do this :
var myBigJsonObj = {
data1 : { //lots of data},
data2 : { //lots of data}
};
and then you had some html like so :
<div data-dataId="data1" id="x">
You can use jquery to get the data now like so :
var dataId = $('#x').attr('data-dataId');
var myData = myBigJsonObj[dataId];
This is the best approach imho.
While there's nothing to stop you embedding a long string of JSON in a data attribute, arguably the more "correct" way of doing it would be to add one data attribute per property of the JSON data. eg:
Javascript:
var dataObj = { foo: 'something', bar: 'something else' }
HTML:
<div data-foo="something" data-bar="something else"></div>
This way each piece of data in the JSON object corresponds to a separate, independently-accessible piece of data attached to the DOM element.
Bear in mind that either way you'll need to escape the values you're inserting into the HTML - otherwise stray " characters will break your page.
You could make use of Map. Where your element will be the key, and the value at that key could be an object in which you store wanted data. Something like this (not tested though):
(function(global) {
const map = new Map();
global.CustomData = {
add(element, key, data) {
if (!map.has(element)) {
map.set(element, {});
}
map.get(element)[key] = data;
return map.get(element);
},
get(element, key) {
if (!map.has(element)) {
return null;
}
if (key !== undefined) {
return map.get(element)[key];
}
return map.get(element)
},
remove(element, key) {
if (!map.has(element)) {
return false;
}
delete map.get(element)[key];
if (Object.keys(map.get(element)).length === 0) {
map.delete(element);
}
return true;
},
clear(element) {
if (!map.has(element)) {
return false;
}
map.delete(element);
return true;
}
}
})(window);