180

I am storing data using the data- approach in a HTML tag like so:

<td><"button class='delete' data-imagename='"+results[i].name+"'>Delete"</button></td>

I am then retrieving the data in a callback like this:

$(this).data('imagename');

That works fine. What I am stuck on is trying to save the object instead of just one of the properties of it. I tried to do this:

<td><button class='delete' data-image='"+results[i]+"'>Delete</button></td>

Then I tried to access the name property like this:

var imageObj = $(this).data('image');
console.log('Image name: '+imageObj.name);

The log tells me undefined. So it seems like I can store simple strings in the data- attributes but I can't store JSON objects...

I've also tried to use this kid of syntax with no luck:

<div data-foobar='{"foo":"bar"}'></div>

Any idea on how to store an actual object in the HTML tag using the data- approach?

15 Answers 15

190

Actually, your last example:

<div data-foobar='{"foo":"bar"}'></div>

seems to be working well (see http://jsfiddle.net/GlauberRocha/Q6kKU/).

The nice thing is that the string in the data- attribute is automatically converted to a JavaScript object. I don't see any drawback in this approach, on the contrary! One attribute is sufficient to store a whole set of data, ready to use in JavaScript through object properties.

(Note: for the data- attributes to be automatically given the type Object rather than String, you must be careful to write valid JSON, in particular to enclose the key names in double quotes).

Sign up to request clarification or add additional context in comments.

11 Comments

If it helps anyone, here's how to access the above: $('div').data('foobar').foo. api.jquery.com/data
@GlauberRocha, What if data contains single quote? ' is not working for me while i echo json_encode($array) from php. Since it will terminate attribute value by single quote. Any suggestion except escaping single quote manually from array.?
@Log1c ツ Just an idea: try encoding your ' as &amp;quot; (double-escaped HTML entity) so it's rendered in your source as &quot;. But maybe that's the kind of thing you want to avoid when you say "escaping single quote manually"...
@GlauberRocha thanks for the reply. I solved it using same trick. I used htmlspecialchars()[php.net/manual/en/function.htmlspecialchars.php] . It solved. :)
single quotes can cause problems, for a future proof solution use the answer mentioned base64 encoding data...
|
163

instead of embedding it in the text just use $('#myElement').data('key',jsonObject);

it won't actually be stored in the html, but if you're using jquery.data, all that is abstracted anyway.

To get the JSON back don't parse it, just call:

var getBackMyJSON = $('#myElement').data('key');

If you are getting [Object Object] instead of direct JSON, just access your JSON by the data key:

var getBackMyJSON = $('#myElement').data('key').key;

4 Comments

So using the data- approach allows me to store the value for each delete button (each button gets a different json object...) I have in the table by putting in the hmtl tag like I showed above. Is what you're suggesting going to allow me to associate each object with to the corresponding delete button? How would I do that, how would I use $('#myElement'). in the same way? Sorry, I'm not experienced on this. Thanks
So I ended up assigning an index to each html button: <td><button class='delete' data-index='"+i+"' >Delete</button></td>, and storing an array of JSON objects in a $objects variable. Then when a button is clicked I look at the button index by doing: var buttonIndex = $(this).data('index'); and then I get the corresponding object from the previously saved like this: $objects[buttonIndex]. This works fine, not sure if it's the correct way of doing it. Thanks for your feedback!
If the field contains the JSON from PHP encoding, you might just want to do this instead: htmlspecialchars(json_encode($e)) (idea from Nicolas answer comments).
in the first example, does jsonObject need to be stringified? edit: in case it helps anyone else, i just found the answer to that question here: stackoverflow.com/a/42864472 "You don't need to stringify objects to store them using jQuery.data()"
87

This is how it worked for me.

Object

var my_object ={"Super Hero":["Iron Man", "Super Man"]};

Set

Encode the stringified object with encodeURIComponent() and set as attribute:

var data_str = encodeURIComponent(JSON.stringify(my_object));
$("div#mydiv").attr("data-hero",data-str);

Get

To get the value as an object, parse the decoded, with decodeURIComponent(), attribute value:

var data_str = $("div#mydiv").attr("data-hero");
var my_object = JSON.parse(decodeURIComponent(data_str));

1 Comment

this seems much more robust than the other options when it comes to handling and escaping quotes
30

A lot of problems with storing serialized data can be solved by converting the serialized string to base64.

A base64 string can be accepted just about anywhere with no fuss.

Take a look at:

The WindowOrWorkerGlobalScope.btoa() method creates a base-64 encoded ASCII string from a String object in which each character in the string is treated as a byte of binary data.

The WindowOrWorkerGlobalScope.atob() function decodes a string of data which has been encoded using base-64 encoding.

Convert to/from as needed.

5 Comments

This works really well for passing complex Objects into attributes.
Unfortunately, boot has Unicode problem and is not suitable for all languages.
For the browser use window.btoa
This method is pretty bulletproof IMO. However, once you retrieve and un-encode your base64 string, you have serialized JSON. So you need touse JSON.parse before you can use the result as an object.
this is amazing i never knew is was possible thank you so much for sharing!
30

There's a better way of storing JSON in the HTML:

HTML

<script id="some-data" type="application/json">{"param_1": "Value 1", "param_2": "Value 2"}</script>

JavaScript

JSON.parse(document.getElementById('some-data').textContent);

1 Comment

You are the real savior. Out of all the solutions available online, this is the most apt and clean solution.
17

Combine the use of window.btoa and window.atob together with JSON.stringify and JSON.parse.

- This works for strings containing single quotes

Encoding the data:

var encodedObject = window.btoa(JSON.stringify(dataObject));

Decoding the data:

var dataObject = JSON.parse(window.atob(encodedObject));

Here is an example of how the data is constructed and decoded later with the click event.

Construct the html and encode the data:

var encodedObject = window.btoa(JSON.stringify(dataObject));

"<td>" + "<a class='eventClass' href='#' data-topic='" + encodedObject + "'>" 
+ "Edit</a></td>"

Decode the data in the click event handler:

$("#someElementID").on('click', 'eventClass', function(e) {
            event.preventDefault();
            var encodedObject = e.target.attributes["data-topic"].value;
            var dataObject = JSON.parse(window.atob(encodedObject));

            // use the dataObject["keyName"] 
}

Comments

13

For me it work like that, as I need to store it in template...

// Generate HTML
var gridHtml = '<div data-dataObj=\''+JSON.stringify(dataObj).replace(/'/g, "\\'");+'\'></div>';

// Later
var dataObj = $('div').data('dataObj'); // jQuery automatically unescape it

4 Comments

thanks for sharing..exactly what I was looking for...kept getting [Object Object] when trying to parse the accepted answer.
@greaterKing you don't parse the JSON from accepted answer, you just access it through the key which is same as the data name so if you have e.g. $('body').data('myData', { h: "hello", w: "world" }) _____________________________________________________________________________________________ you would get your JSON object by $('body').data().myData
To simplify, you can do '<div data-dataObj=\''+ JSON.stringify(dataObj) +'\'></div>'. Those are all single quotes, the beginning and end are just escaped, so it would be the same as having '{"some":"thing"}'
@IamFace - replace() addresses the possibility of single quotes appearing in the json data, which is entirely possible.
3

The trick for me was to add double quotes around keys and values. If you use a PHP function like json_encode will give you a JSON encoded string and an idea how to properly encode yours.

jQuery('#elm-id').data('datakey') will return an object of the string, if the string is properly encoded as json.

As per jQuery documentation: (http://api.jquery.com/jquery.parsejson/)

Passing in a malformed JSON string results in a JavaScript exception being thrown. For example, the following are all invalid JSON strings:

  1. "{test: 1}" (test does not have double quotes around it).
  2. "{'test': 1}" ('test' is using single quotes instead of double quotes).
  3. "'test'" ('test' is using single quotes instead of double quotes).
  4. ".1" (a number must start with a digit; "0.1" would be valid).
  5. "undefined" (undefined cannot be represented in a JSON string; null, however, can be).
  6. "NaN" (NaN cannot be represented in a JSON string; direct representation of Infinity is also n

Comments

1

This code is working fine for me.

Encode data with btoa

let data_str = btoa(JSON.stringify(jsonData));
$("#target_id").attr('data-json', data_str);

And then decode it with atob

let tourData = $(this).data("json");
tourData = atob(tourData);

1 Comment

Unfortunately, boot has Unicode problem and is not suitable for all languages.
0

Using the documented jquery .data(obj) syntax allows you to store an object on the DOM element. Inspecting the element will not show the data- attribute because there is no key specified for the value of the object. However, data within the object can be referenced by key with .data("foo") or the entire object can be returned with .data().

So assuming you set up a loop and result[i] = { name: "image_name" } :

$('.delete')[i].data(results[i]); // => <button class="delete">Delete</delete>
$('.delete')[i].data('name'); // => "image_name"
$('.delete')[i].data(); // => { name: "image_name" }

Comments

0

For some reason, the accepted answer worked for me only if being used once on the page, but in my case I was trying to save data on many elements on the page and the data was somehow lost on all except the first element.

As an alternative, I ended up writing the data out to the dom and parsing it back in when needed. Perhaps it's less efficient, but worked well for my purpose because I'm really prototyping data and not writing this for production.

To save the data I used:

$('#myElement').attr('data-key', JSON.stringify(jsonObject));

To then read the data back is the same as the accepted answer, namely:

var getBackMyJSON = $('#myElement').data('key');

Doing it this way also made the data appear in the dom if I were to inspect the element with Chrome's debugger.

Comments

0

.data() works perfectly for most cases. The only time I had a problem was when the JSON string itself had a single quote. I could not find any easy way to get past this so resorted to this approach (am using Coldfusion as server language):

    <!DOCTYPE html>
        <html>
            <head>
                <title>
                    Special Chars in Data Attribute
                </title>
                <meta http-equiv="X-UA-Compatible" content="IE=edge">
                <script src="https://code.jquery.com/jquery-1.12.2.min.js"></script>
                <script>
                    $(function(){
                        var o = $("##xxx");
                        /**
                            1. get the data attribute as a string using attr()
                            2. unescape
                            3. convert unescaped string back to object
                            4. set the original data attribute to future calls get it as JSON.
                        */
                        o.data("xxx",jQuery.parseJSON(unescape(o.attr("data-xxx"))));
                        console.log(o.data("xxx")); // this is JSON object.
                    });
                </script>
                <title>
                    Title of the document
                </title>
            </head>
            <body>
                <cfset str = {name:"o'reilly's stuff",code:1}>
<!-- urlencode is a CF function to UTF8 the string, serializeJSON converts object to strin -->
                <div id="xxx" data-xxx='#urlencodedformat(serializejson(str))#'>
                </div>
            </body>
        </html>

Comments

0

For the record, I found the following code works. It enables you to retrieve the array from the data tag, push a new element on, and store it back in the data tag in the correct JSON format. The same code can therefore be used again to add further elements to the array if desired. I found that $('#my-data-div').attr('data-namesarray', names_string); correctly stores the array, but $('#my-data-div').data('namesarray', names_string); doesn't work.

<div id="my-data-div" data-namesarray='[]'></div>

var names_array = $('#my-data-div').data('namesarray');
names_array.push("Baz Smith");
var names_string = JSON.stringify(names_array);
$('#my-data-div').attr('data-namesarray', names_string);

Comments

0
!DOCTYPE html>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
$("#btn1").click(function()
{
person = new Object();
person.name = "vishal";
person.age =20;
    $("div").data(person);
});
  $("#btn2").click(function()
{
    alert($("div").data("name"));
});

});

</script>
<body>
<button id="btn1">Attach data to div element</button><br>
<button id="btn2">Get data attached to div element</button>
<div></div>
</body>


</html>

Anser:-Attach data to selected elements using an object with name/value pairs.
GET value using object propetis like name,age etc...

Comments

0

I found a better way in https://oblik.dev/utilities/config/ Basically what they do is have a parser from-to json-like objects without double quotes:

import { Parser } from 'oblik/utils/config'

let parser = new Parser()
let result = parser.parse('foo: bar, !baz')
console.log(result) // { foo: "bar", baz: false }

More examples:

<div ob-foo="text: Hello, num: 42">My Foo component</div>

I would like to see something like this format standartized

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.