Stocker l'objet JSON dans l'attribut de données dans HTML jQuery

134

Je stocke des données en utilisant l' data-approche dans une balise HTML comme ceci:

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

Je récupère ensuite les données dans un rappel comme celui-ci:

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

Cela fonctionne très bien. Ce sur quoi je suis coincé, c'est d'essayer de sauvegarder l'objet au lieu d'une seule de ses propriétés. J'ai essayé de faire ceci:

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

Ensuite, j'ai essayé d'accéder à la propriété name comme ceci:

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

Le journal me dit undefined. Il semble donc que je puisse stocker des chaînes simples dans les data-attributs mais je ne peux pas stocker d'objets JSON ...

J'ai également essayé d'utiliser ce gamin de syntaxe sans succès:

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

Une idée sur la façon de stocker un objet réel dans la balise HTML en utilisant l' data-approche?

zumzum
la source

Réponses:

140

au lieu de l'incorporer dans le texte, utilisez simplement $('#myElement').data('key',jsonObject);

il ne sera pas réellement stocké dans le html, mais si vous utilisez jquery.data, tout cela est de toute façon abstrait.

Pour récupérer le JSON, ne l'analysez pas , appelez simplement:

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

Si vous obtenez [Object Object]au lieu du JSON direct, accédez simplement à votre JSON par la clé de données:

var getBackMyJSON = $('#myElement').data('key').key;
nathan gonzalez
la source
1
Donc, utiliser l'approche data me permet de stocker la valeur de chaque bouton de suppression (chaque bouton obtient un objet json différent ...) que j'ai dans le tableau en insérant la balise hmtl comme je l'ai montré ci-dessus. Est-ce que ce que vous suggérez va me permettre d'associer chaque objet au bouton de suppression correspondant? Comment ferais-je cela, comment utiliserais-je $ ('# myElement'). de la même manière? Désolé, je n'ai pas d'expérience dans ce domaine. Merci
zumzum
J'ai donc fini par attribuer un index à chaque bouton html: <td> <button class = 'delete' data-index = '"+ i +"'> Supprimer </button> </td>, et stocker un tableau d'objets JSON dans une variable $ objects. Ensuite, lorsqu'un bouton est cliqué, je regarde l'index du bouton en faisant: var buttonIndex = $ (this) .data ('index'); puis j'obtiens l'objet correspondant de la sauvegarde précédemment comme ceci: $ objets [buttonIndex]. Cela fonctionne bien, je ne sais pas si c'est la bonne façon de le faire. Merci pour vos commentaires!
zumzum
Si le champ contient le JSON de l'encodage PHP, vous voudrez peut-être simplement le faire à la place: htmlspecialchars(json_encode($e))(idée de Nicolas répondre aux commentaires).
CPHPython
dans le premier exemple, doit- jsonObjectil être stringifié? edit: au cas où cela aiderait quelqu'un d'autre, je viens de trouver la réponse à cette question ici: stackoverflow.com/a/42864472 "You don't need to stringify objects to store them using jQuery.data()"
user1063287
154

En fait, votre dernier exemple:

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

semble bien fonctionner (voir http://jsfiddle.net/GlauberRocha/Q6kKU/ ).

La bonne chose est que la chaîne de l'attribut data est automatiquement convertie en objet JavaScript. Je ne vois aucun inconvénient à cette approche, bien au contraire! Un attribut suffit pour stocker tout un ensemble de données, prêtes à être utilisées en JavaScript via les propriétés d'objet.

(Remarque: pour que les attributs de données reçoivent automatiquement le type Object plutôt que String, vous devez faire attention à écrire du JSON valide, en particulier à mettre les noms de clés entre guillemets).

Nicolas Le Thierry d'Ennequin
la source
20
Si cela peut aider tout le monde, voici comment accéder au - dessus: $('div').data('foobar').foo. api.jquery.com/data
Gary
5
@GlauberRocha, que faire si les données contiennent des guillemets simples? 'ne fonctionne pas pour moi pendant que je suis echo json_encode($array)de php. Puisqu'il terminera la valeur d'attribut par un guillemet simple. Toute suggestion, sauf échapper manuellement au guillemet simple du tableau.?
Ravi Dhoriya ツ
1
@ Log1c ツ Juste une idée: essayez d'encoder votre 'as &amp;quot;(entité HTML à double échappement ) pour qu'il soit rendu dans votre source comme & quot ;. Mais peut-être que c'est le genre de chose que vous voulez éviter lorsque vous dites "échapper manuellement aux guillemets simples" ...
Nicolas Le Thierry d'Ennequin
2
@GlauberRocha merci pour la réponse. Je l'ai résolu en utilisant la même astuce. J'ai utilisé htmlspecialchars () [ php.net/manual/en/function.htmlspecialchars.php] . Cela a résolu. :)
Ravi Dhoriya ツ
1
J'ai rencontré des problèmes avec cette méthode lorsque l'une des propriétés de l'objet était une chaîne contenant un guillemet simple. L'attribut data se termine au premier guillemet simple rencontré et comme il n'est pas JSON valide, il est interprété comme une chaîne. Il est peut-être possible d'encoder la chaîne, mais j'ai trouvé que la solution la plus simple était d'utiliser simplement plusieurs attributs de données.
Jon Hulka
43

Voilà comment cela a fonctionné pour moi.

Objet

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

Ensemble

Encode l'objet stringifié avec encodeURIComponent () et défini comme attribut:

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

Avoir

Pour obtenir la valeur en tant qu'objet, analysez la valeur décodée, avec decodeURIComponent () , valeur d'attribut:

var data_str = $("div#mydiv").attr("data-hero");
var my_object = JSON.parse(decodeURIComponent(data_str));
Sathvik reddy Gaddam
la source
14

De nombreux problèmes liés au stockage des données sérialisées peuvent être résolus en convertissant la chaîne sérialisée en base64 .

Une chaîne base64 peut être acceptée à peu près n'importe où sans problème.

Jeter un coup d'œil à:

La WindowOrWorkerGlobalScope.btoa()méthode crée une chaîne ASCII codée en base 64 à partir d'un objet String dans lequel chaque caractère de la chaîne est traité comme un octet de données binaires.

La WindowOrWorkerGlobalScope.atob()fonction décode une chaîne de données qui a été codée en utilisant un codage en base 64.

Convertissez vers / depuis si nécessaire.

Dan
la source
Cela fonctionne très bien pour passer des objets complexes en attributs.
baacke
Malheureusement, le démarrage a un problème Unicode et ne convient pas à toutes les langues.
AhmadJavadiNejad
Pour l'utilisation du navigateurwindow.btoa
Henry
1
Cette méthode est assez à l'épreuve des balles IMO. Cependant, une fois que vous avez récupéré et décodé votre chaîne base64, vous avez sérialisé JSON. Vous devez donc les utiliser JSON.parseavant de pouvoir utiliser le résultat comme objet.
Henry
13

Pour moi, cela fonctionne comme ça, car je dois le stocker dans un modèle ...

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

// Later
var dataObj = $('div').data('dataObj'); // jQuery automatically unescape it
molokoloco
la source
1
merci pour le partage..exactement ce que je cherchais ... a continué à obtenir [Object Object] en essayant d'analyser la réponse acceptée.
GreaterKing
@greaterKing vous n'analysez pas le JSON à partir de la réponse acceptée, vous y accédez simplement via la clé qui est la même que le nom des données, donc si vous avez par exemple $('body').data('myData', { h: "hello", w: "world" })_____________________________________________________________________________________________ vous obtiendrez votre objet JSON par$('body').data().myData
jave.web
Pour simplifier, vous pouvez le faire '<div data-dataObj=\''+ JSON.stringify(dataObj) +'\'></div>'. Ce sont tous des guillemets simples, le début et la fin sont simplement échappés, donc ce serait la même chose que d'avoir'{"some":"thing"}'
IamFace
1
@IamFace - replace()aborde la possibilité que des guillemets simples apparaissent dans les données json, ce qui est tout à fait possible.
billynoah
3

L'astuce pour moi était d' ajouter des guillemets doubles autour des clés et des valeurs . Si vous utilisez une fonction PHP comme json_encodecela vous donnera une chaîne encodée JSON et une idée de comment encoder correctement la vôtre.

jQuery('#elm-id').data('datakey') retournera un objet de la chaîne, si la chaîne est correctement codée en json.

Selon la documentation jQuery: ( http://api.jquery.com/jquery.parsejson/ )

La transmission d'une chaîne JSON mal formée entraîne la levée d'une exception JavaScript. Par exemple, les éléments suivants sont toutes des chaînes JSON non valides:

  1. "{test: 1}"( testn'a pas de guillemets doubles autour).
  2. "{'test': 1}"( 'test'utilise des guillemets simples au lieu de guillemets doubles).
  3. "'test'"( 'test'utilise des guillemets simples au lieu de guillemets doubles).
  4. ".1"(un nombre doit commencer par un chiffre; "0.1"serait valide).
  5. "undefined"( undefinedne peut pas être représenté dans une chaîne JSON null, mais peut l'être).
  6. "NaN"( NaNne peut pas être représenté dans une chaîne JSON; la représentation directe d'Infinity est également n
George Donev
la source
2

Combinez l'utilisation de window.btoaet window.atobavec JSON.stringifyet JSON.parse.

- Cela fonctionne pour les chaînes contenant des guillemets simples

Encodage des données:

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

Décodage des données:

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

Voici un exemple de la manière dont les données sont construites et décodées ultérieurement avec l'événement click.

Construisez le html et encodez les données:

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

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

Décodez les données dans le gestionnaire d'événements click:

$("#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"] 
}
Wayne
la source
0

L'utilisation de la syntaxe documentée jquery .data (obj) vous permet de stocker un objet sur l'élément DOM. L'inspection de l'élément n'affichera pas l' data-attribut car aucune clé n'est spécifiée pour la valeur de l'objet. Cependant, les données dans l'objet peuvent être référencées par clé avec .data("foo")ou l'objet entier peut être renvoyé avec .data().

Donc, en supposant que vous configuriez une boucle et 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" }
user2069751
la source
0

Pour une raison quelconque, la réponse acceptée ne fonctionnait pour moi que si elle était utilisée une fois sur la page, mais dans mon cas, j'essayais de sauvegarder des données sur de nombreux éléments de la page et les données étaient en quelque sorte perdues sur tous sauf le premier élément.

Au lieu de cela, j'ai fini par écrire les données sur le dom et les analyser en cas de besoin. Peut-être que c'est moins efficace, mais cela a bien fonctionné pour mon objectif parce que je suis vraiment en train de prototyper des données et je n'écris pas cela pour la production.

Pour enregistrer les données que j'ai utilisées:

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

Relire ensuite les données équivaut à la réponse acceptée, à savoir:

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

Cela faisait également apparaître les données dans le dom si je devais inspecter l'élément avec le débogueur de Chrome.

Shane E.
la source
0

.data()fonctionne parfaitement dans la plupart des cas. La seule fois où j'ai eu un problème, c'était lorsque la chaîne JSON elle-même avait un guillemet simple. Je ne pouvais pas trouver de moyen facile de surmonter cela, alors j'ai eu recours à cette approche (j'utilise Coldfusion comme langage serveur):

    <!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>
Sajjan Sarkar
la source
0

Pour mémoire, j'ai trouvé que le code suivant fonctionne. Il vous permet de récupérer le tableau à partir de la balise de données, de pousser un nouvel élément et de le stocker de nouveau dans la balise de données au format JSON correct. Le même code peut donc être utilisé à nouveau pour ajouter d'autres éléments au tableau si vous le souhaitez. J'ai trouvé que $('#my-data-div').attr('data-namesarray', names_string);stockait correctement le tableau, mais $('#my-data-div').data('namesarray', names_string);ne fonctionnait pas.

<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);
Bazley
la source
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...
Vishal Patel
la source
0

Ce code fonctionne bien pour moi.

Encoder des données avec btoa

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

Et puis décoder avec atob

let tourData = $(this).data("json");
tourData = atob(tourData);
Hp Sharma
la source
Malheureusement, le démarrage a un problème Unicode et ne convient pas à toutes les langues.
AhmadJavadiNejad