Almacenar objeto JSON en atributo de datos en HTML jQuery

134

Estoy almacenando datos usando el data-enfoque en una etiqueta HTML de esta manera:

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

Luego estoy recuperando los datos en una devolución de llamada como esta:

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

Eso funciona bien Lo que estoy atascado es tratar de guardar el objeto en lugar de solo una de sus propiedades. Traté de hacer esto:

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

Luego intenté acceder a la propiedad de nombre de esta manera:

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

El registro me lo dice undefined. Entonces parece que puedo almacenar cadenas simples en los data-atributos pero no puedo almacenar objetos JSON ...

También intenté usar este tipo de sintaxis sin suerte:

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

¿Alguna idea sobre cómo almacenar un objeto real en la etiqueta HTML utilizando el data-enfoque?

zumzum
fuente

Respuestas:

140

en lugar de incrustarlo en el texto solo usa $('#myElement').data('key',jsonObject);

en realidad no se almacenará en el html, pero si está usando jquery.data, todo eso se abstrae de todos modos.

Para recuperar el JSON , no lo analice , simplemente llame:

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

Si obtiene en [Object Object]lugar de JSON directo, simplemente acceda a su JSON mediante la clave de datos:

var getBackMyJSON = $('#myElement').data('key').key;
nathan gonzalez
fuente
1
Por lo tanto, usar el enfoque de datos me permite almacenar el valor de cada botón de eliminación (cada botón obtiene un objeto json diferente ...) que tengo en la tabla al poner la etiqueta hmtl como se muestra arriba. ¿Lo que estás sugiriendo me permitirá asociar cada objeto al botón de eliminación correspondiente? ¿Cómo haría eso? ¿Cómo usaría $ ('# myElement')? ¿del mismo modo? Lo siento, no tengo experiencia en esto. Gracias
zumzum
Así que terminé asignando un índice a cada botón html: <td> <button class = 'delete' data-index = '"+ i +"'> Delete </button> </td>, y almacenando una matriz de objetos JSON en una variable de $ objetos. Luego, cuando se hace clic en un botón, miro el índice del botón haciendo: var buttonIndex = $ (this) .data ('index'); y luego obtengo el objeto correspondiente del guardado previamente de esta manera: $ objetos [buttonIndex]. Esto funciona bien, no estoy seguro si es la forma correcta de hacerlo. Gracias por tus comentarios!
zumzum
Si el campo contiene el JSON de la codificación PHP, es posible que desee hacer esto en su lugar: htmlspecialchars(json_encode($e))(idea de los comentarios de respuesta de Nicolas ).
CPHPython
en el primer ejemplo, ¿ jsonObjectnecesita ser stringified? editar: en caso de que ayude a alguien más, acabo de encontrar la respuesta a esa pregunta aquí: stackoverflow.com/a/42864472 "You don't need to stringify objects to store them using jQuery.data()"
user1063287
154

En realidad, tu último ejemplo:

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

parece estar funcionando bien (ver http://jsfiddle.net/GlauberRocha/Q6kKU/ ).

Lo bueno es que la cadena en el atributo de datos se convierte automáticamente en un objeto JavaScript. ¡No veo ningún inconveniente en este enfoque, al contrario! Un atributo es suficiente para almacenar un conjunto completo de datos, listo para usar en JavaScript a través de las propiedades del objeto.

(Nota: para que los atributos de datos reciban automáticamente el tipo Objeto en lugar de Cadena, debe tener cuidado de escribir un JSON válido, en particular para encerrar los nombres clave entre comillas dobles).

Nicolas Le Thierry d'Ennequin
fuente
20
Si se ayuda a nadie, aquí es cómo acceder a los anteriores: $('div').data('foobar').foo. api.jquery.com/data
Gary
55
@GlauberRocha, ¿Qué pasa si los datos contienen comillas simples? 'no funciona para mí mientras estoy echo json_encode($array)en php. Dado que terminará el valor del atributo con comillas simples. ¿Alguna sugerencia, excepto escapar de comillas simples manualmente de la matriz?
Ravi Dhoriya ツ
1
@ Log1c ツ Solo una idea: intente codificar su 'as &amp;quot;(entidad HTML de doble escape) para que se represente en su fuente como & quot ;. Pero tal vez ese es el tipo de cosas que quieres evitar cuando dices "escapar de una cita simple manualmente" ...
Nicolas Le Thierry d'Ennequin
2
@GlauberRocha gracias por la respuesta. Lo resolví usando el mismo truco. Usé htmlspecialchars () [ php.net/manual/en/function.htmlspecialchars.php] . Resuelto :)
Ravi Dhoriya ツ
1
Me encontré con problemas al usar este método cuando una de las propiedades del objeto era una cadena que contenía una comilla simple. El atributo de datos termina en la primera cita simple encontrada y, dado que no es un JSON válido, se interpreta como una cadena. Puede que sea posible codificar la cadena, pero descubrí que la solución más fácil era usar solo múltiples atributos de datos.
Jon Hulka
43

Así es como funcionó para mí.

Objeto

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

Conjunto

Codifique el objeto en cadena con encodeURIComponent () y establezca como atributo:

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

Obtener

Para obtener el valor como un objeto, analice el valor de atributo decodificado, con decodeURIComponent () :

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

Se pueden resolver muchos problemas con el almacenamiento de datos serializados convirtiendo la cadena serializada a base64 .

Se puede aceptar una cadena base64 en casi cualquier lugar sin problemas.

Echa un vistazo a:

El WindowOrWorkerGlobalScope.btoa()método crea una cadena ASCII codificada en base 64 a partir de un objeto String en el que cada carácter de la cadena se trata como un byte de datos binarios.

La WindowOrWorkerGlobalScope.atob()función decodifica una cadena de datos que ha sido codificada usando codificación base-64.

Convierte a / desde según sea necesario.

Dan
fuente
Esto funciona muy bien para pasar objetos complejos a atributos.
baacke
Desafortunadamente, el arranque tiene un problema Unicode y no es adecuado para todos los idiomas.
AhmadJavadiNejad
Para el uso del navegadorwindow.btoa
Henry
1
Este método es bastante a prueba de balas IMO. Sin embargo, una vez que recupera y descodifica su cadena base64, ha serializado JSON. Por lo tanto, debe JSON.parseusar antes de poder usar el resultado como un objeto.
Henry
13

Para mí funciona así, ya que necesito almacenarlo en una plantilla ...

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

// Later
var dataObj = $('div').data('dataObj'); // jQuery automatically unescape it
molokoloco
fuente
1
gracias por compartir ... exactamente lo que estaba buscando ... seguía obteniendo [Object Object] cuando intentaba analizar la respuesta aceptada.
GreaterKing
@greaterKing no analiza el JSON de la respuesta aceptada, simplemente accede a él a través de la clave que es el mismo que el nombre de los datos, por lo que si tiene, por ejemplo, $('body').data('myData', { h: "hello", w: "world" })_____________________________________________________________________________________________ obtendrá su objeto JSON en$('body').data().myData
jave.web
Para simplificar, puedes hacer '<div data-dataObj=\''+ JSON.stringify(dataObj) +'\'></div>'. Esas son todas comillas simples, el principio y el final simplemente se escapan, por lo que sería lo mismo que tener'{"some":"thing"}'
IamFace
1
@IamFace: replace()aborda la posibilidad de que aparezcan comillas simples en los datos json, lo cual es completamente posible.
billynoah
3

El truco para mí fue agregar comillas dobles alrededor de las claves y los valores . Si usa una función PHP como json_encodele dará una cadena codificada JSON y una idea de cómo codificar correctamente la suya.

jQuery('#elm-id').data('datakey') devolverá un objeto de la cadena, si la cadena está codificada correctamente como json.

Según la documentación de jQuery: ( http://api.jquery.com/jquery.parsejson/ )

Al pasar una cadena JSON con formato incorrecto, se genera una excepción de JavaScript. Por ejemplo, las siguientes son todas las cadenas JSON no válidas:

  1. "{test: 1}"( testno tiene comillas dobles a su alrededor).
  2. "{'test': 1}"( 'test'utiliza comillas simples en lugar de comillas dobles).
  3. "'test'"( 'test'utiliza comillas simples en lugar de comillas dobles).
  4. ".1"(un número debe comenzar con un dígito; "0.1"sería válido).
  5. "undefined"( undefinedno se puede representar en una cadena JSON; nullsin embargo, se puede representar).
  6. "NaN"( NaNno se puede representar en una cadena JSON; la representación directa de Infinity también es n
George Donev
fuente
2

Combina el uso de window.btoay window.atobjunto con JSON.stringifyy JSON.parse.

- Esto funciona para cadenas que contienen comillas simples

Codificación de los datos:

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

Decodificando los datos:

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

Aquí hay un ejemplo de cómo se construyen y decodifican los datos más tarde con el evento click.

Construya el html y codifique los datos:

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

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

Decodifique los datos en el controlador de eventos 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
fuente
0

El uso de la sintaxis documentada jquery .data (obj) le permite almacenar un objeto en el elemento DOM. La inspección del elemento no mostrará el data-atributo porque no hay una clave especificada para el valor del objeto. Sin embargo, los datos dentro del objeto pueden ser referenciados por clave con .data("foo")o todo el objeto puede ser devuelto con .data().

Asumiendo que configura un bucle y 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" }
usuario2069751
fuente
0

Por alguna razón, la respuesta aceptada funcionó para mí solo si se usaba una vez en la página, pero en mi caso estaba tratando de guardar datos en muchos elementos de la página y los datos se perdieron de alguna manera en todos, excepto en el primer elemento.

Como alternativa, terminé escribiendo los datos en el dom y analizándolos nuevamente cuando era necesario. Quizás sea menos eficiente, pero funcionó bien para mi propósito porque realmente estoy creando prototipos de datos y no escribiendo esto para la producción.

Para guardar los datos que utilicé:

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

Luego, leer los datos nuevamente es lo mismo que la respuesta aceptada, a saber:

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

Hacerlo de esta manera también hizo que los datos aparecieran en el dom si tuviera que inspeccionar el elemento con el depurador de Chrome.

Shane E.
fuente
0

.data()Funciona perfectamente para la mayoría de los casos. La única vez que tuve un problema fue cuando la cadena JSON tenía una comilla simple. No pude encontrar ninguna manera fácil de superar esto, así que recurrí a este enfoque (estoy usando Coldfusion como lenguaje de servidor):

    <!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
fuente
0

Para el registro, encontré que el siguiente código funciona. Le permite recuperar la matriz de la etiqueta de datos, activar un nuevo elemento y almacenarlo nuevamente en la etiqueta de datos en el formato JSON correcto. Por lo tanto, se puede usar el mismo código nuevamente para agregar más elementos a la matriz si se desea. Descubrí que $('#my-data-div').attr('data-namesarray', names_string);almacena correctamente la matriz, pero $('#my-data-div').data('namesarray', names_string);no funciona.

<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
fuente
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
fuente
0

Este código está funcionando bien para mí.

Codificar datos con btoa

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

Y luego descifrarlo con atob

let tourData = $(this).data("json");
tourData = atob(tourData);
HP Sharma
fuente
Desafortunadamente, el arranque tiene un problema Unicode y no es adecuado para todos los idiomas.
AhmadJavadiNejad