Armazenar objeto JSON no atributo de dados no HTML jQuery

134

Estou armazenando dados usando a data-abordagem em uma tag HTML da seguinte forma:

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

Em seguida, estou recuperando os dados em um retorno de chamada como este:

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

Isso funciona bem. O que eu estou preso é tentar salvar o objeto em vez de apenas uma das propriedades dele. Eu tentei fazer isso:

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

Então eu tentei acessar a propriedade name assim:

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

O log me diz undefined. Parece que posso armazenar cadeias simples nos data-atributos, mas não consigo armazenar objetos JSON ...

Eu também tentei usar esse garoto de sintaxe sem sorte:

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

Alguma idéia de como armazenar um objeto real na tag HTML usando a data-abordagem?

zumzum
fonte

Respostas:

140

em vez de incorporá-lo no texto, basta usar $('#myElement').data('key',jsonObject);

na verdade, ele não será armazenado no html, mas se você estiver usando jquery.data, tudo isso será abstraído de qualquer maneira.

Para recuperar o JSON , não o analise , basta chamar:

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

Se você estiver obtendo, em [Object Object]vez de JSON direto, basta acessar seu JSON pela chave de dados:

var getBackMyJSON = $('#myElement').data('key').key;
nathan gonzalez
fonte
1
Portanto, o uso da abordagem de dados permite que eu armazene o valor de cada botão de exclusão (cada botão recebe um objeto json diferente ...) que tenho na tabela colocando a tag hmtl como mostrei acima. O que você está sugerindo me permitirá associar cada objeto ao botão de exclusão correspondente? Como eu faria isso, como eu usaria $ ('# myElement'). do mesmo jeito? Desculpe, não tenho experiência nisso. Graças
zumzum
Então acabei atribuindo um índice a cada botão html: <td> <button class = 'delete' data-index = '"+ i +"'> Exclua </button> </td> e armazene uma matriz de objetos JSON em uma variável $ objects. Então, quando um botão é clicado, eu olho para o índice do botão fazendo: var buttonIndex = $ (this) .data ('index'); e então obtenho o objeto correspondente dos salvos anteriormente, como este: $ objects [buttonIndex]. Isso funciona bem, não tenho certeza se é a maneira correta de fazê-lo. Obrigado pelo seu feedback!
Zumzum
Se o campo contiver a codificação JSON do PHP, você pode fazer isso: htmlspecialchars(json_encode($e))(idéia de Nicolas responder aos comentários).
CPHPython
no primeiro exemplo, jsonObjectprecisa ser especificado? edit: no caso de ajuda qualquer outra pessoa, eu só encontrei a resposta para essa pergunta aqui: stackoverflow.com/a/42864472 "You don't need to stringify objects to store them using jQuery.data()"
user1063287
154

Na verdade, seu último exemplo:

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

parece estar funcionando bem (consulte http://jsfiddle.net/GlauberRocha/Q6kKU/ ).

O bom é que a string no atributo data é convertida automaticamente em um objeto JavaScript. Não vejo nenhuma desvantagem nessa abordagem, pelo contrário! Um atributo é suficiente para armazenar um conjunto inteiro de dados, pronto para uso em JavaScript por meio das propriedades do objeto.

(Nota: para que os atributos de dados recebam automaticamente o tipo Objeto, em vez de String, você deve ter o cuidado de escrever JSON válido, em particular para colocar os nomes das chaves entre aspas duplas).

Nicolas Le Thierry d'Ennequin
fonte
20
Se isso ajuda ninguém, aqui está como acessar o acima: $('div').data('foobar').foo. api.jquery.com/data
Gary
5
@GlauberRocha, e se os dados contiverem aspas simples? 'não está funcionando para mim enquanto eu echo json_encode($array)do php. Como encerrará o valor do atributo por aspas simples. Qualquer sugestão, exceto escapar aspas simples manualmente da matriz.
Ravi Dhoriyaツ
1
@ Log1c ツ Apenas uma ideia: tente codificar seu 'como &amp;quot;(entidade HTML de escape duplo) para que seja renderizado em sua fonte como'. Mas talvez esse é o tipo de coisa que você quer evitar quando você diz "escapar aspas simples manualmente" ...
Nicolas Le Thierry d'Ennequin
2
@GlauberRocha obrigado pela resposta. Eu resolvi usando o mesmo truque. Eu usei htmlspecialchars () [ php.net/manual/en/function.htmlspecialchars.php] . Resolveu. :)
Ravi Dhoriya ツ
1
Eu tive problemas ao usar esse método quando uma das propriedades do objeto era uma string contendo uma única citação. O atributo data termina na primeira citação única encontrada e, como não é um JSON válido, é interpretado como uma sequência. Pode ser possível codificar a string, mas achei a solução mais fácil apenas usar vários atributos de dados.
precisa saber é o seguinte
43

Foi assim que funcionou para mim.

Objeto

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

Conjunto

Codifique o objeto stringified com encodeURIComponent () e defina como atributo:

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

Obter

Para obter o valor como um objeto, analise o valor do atributo decodificado, com decodeURIComponent (),:

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

Muitos problemas com o armazenamento de dados serializados podem ser resolvidos com a conversão da string serializada em base64 .

Uma string base64 pode ser aceita em qualquer lugar, sem problemas.

Dê uma olhada em:

O WindowOrWorkerGlobalScope.btoa()método cria uma string ASCII codificada em base-64 a partir de um objeto String no qual cada caractere na string é tratado como um byte de dados binários.

A WindowOrWorkerGlobalScope.atob()função decodifica uma sequência de dados que foi codificada usando a codificação base-64.

Converta de / para, conforme necessário.

Dan
fonte
Isso funciona muito bem para passar objetos complexos para atributos.
Baacke
Infelizmente, a inicialização tem um problema Unicode e não é adequado para todos os idiomas.
AhmadJavadiNejad
Para o uso do navegadorwindow.btoa
Henry
1
Este método é bastante IMO à prova de balas. No entanto, depois de recuperar e decodificar sua sequência base64, você serializou o JSON. Portanto, você precisa JSON.parseusar o touse antes de poder usar o resultado como um objeto.
Henry
13

Para mim, funciona assim, pois preciso armazená-lo no modelo ...

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

// Later
var dataObj = $('div').data('dataObj'); // jQuery automatically unescape it
molokoloco
fonte
1
obrigado por compartilhar .. exatamente o que eu estava procurando ... continuava recebendo [Object Object] ao tentar analisar a resposta aceita.
greaterKing
@greaterKing você não analisar o JSON de resposta aceito, basta acessá-lo através da chave que é igual ao nome de dados por isso, se você tem por exemplo $('body').data('myData', { h: "hello", w: "world" })_____________________________________________________________________________________________ você iria receber o seu objeto JSON por$('body').data().myData
jave.web
Para simplificar, você pode fazer '<div data-dataObj=\''+ JSON.stringify(dataObj) +'\'></div>'. Essas são todas as aspas simples, o início eo fim são apenas escaparam, por isso seria o mesmo que ter'{"some":"thing"}'
IamFace
1
@IamFace - replace()aborda a possibilidade de aspas simples aparecerem nos dados do json, o que é totalmente possível.
Billynoah
3

O truque para mim foi adicionar aspas duplas em torno de chaves e valores . Se você usar uma função PHP json_encode, fornecerá uma string codificada em JSON e uma idéia de como codificar corretamente a sua.

jQuery('#elm-id').data('datakey') retornará um objeto da string, se a string estiver codificada corretamente como json.

Conforme a documentação do jQuery: ( http://api.jquery.com/jquery.parsejson/ )

A transmissão de uma sequência JSON malformada resulta no lançamento de uma exceção JavaScript. Por exemplo, a seguir, são todas as seqüências JSON inválidas:

  1. "{test: 1}"( testnão possui aspas duplas).
  2. "{'test': 1}"( 'test'está usando aspas simples em vez de aspas duplas).
  3. "'test'"( 'test'está usando aspas simples em vez de aspas duplas).
  4. ".1"(um número deve começar com um dígito; "0.1"seria válido).
  5. "undefined"( undefinednão pode ser representado em uma sequência JSON; nullno entanto, pode ser).
  6. "NaN"( NaNnão pode ser representado em uma sequência JSON; a representação direta do Infinity também é n
George Donev
fonte
2

Combine o uso de window.btoae window.atobjunto com JSON.stringifye JSON.parse.

- Isso funciona para strings contendo aspas simples

Codificando os dados:

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

Decodificando os dados:

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

Aqui está um exemplo de como os dados são construídos e decodificados posteriormente com o evento click.

Construa o html e codifique os dados:

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

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

Decodifique os dados no manipulador 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
fonte
0

O uso da sintaxe documentada de jquery .data (obj) permite armazenar um objeto no elemento DOM. A inspeção do elemento não mostrará o data-atributo porque não há chave especificada para o valor do objeto. No entanto, os dados dentro do objeto podem ser referenciados por chave com .data("foo")ou o objeto inteiro pode ser retornado com .data().

Supondo que você configure um loop e 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
fonte
0

Por alguma razão, a resposta aceita funcionou para mim apenas se fosse usada uma vez na página, mas no meu caso eu estava tentando salvar dados em muitos elementos da página e os dados foram perdidos de alguma forma em todos, exceto no primeiro elemento.

Como alternativa, acabei escrevendo os dados no Dom e analisando-os quando necessário. Talvez seja menos eficiente, mas funcionou bem para o meu propósito, porque estou realmente fazendo a prototipagem de dados e não escrevendo isso para produção.

Para salvar os dados que eu usei:

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

Ler os dados novamente é o mesmo que a resposta aceita, a saber:

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

Fazer isso dessa maneira também fazia os dados aparecerem no domínio se eu fosse inspecionar o elemento com o depurador do Chrome.

Shane E.
fonte
0

.data()funciona perfeitamente para a maioria dos casos. A única vez que tive um problema foi quando a própria string JSON tinha uma única citação. Não consegui encontrar uma maneira fácil de superar isso, recorrendo a essa abordagem (estou usando o Coldfusion como linguagem 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
fonte
0

Para o registro, eu encontrei o seguinte código funciona. Ele permite recuperar a matriz da tag de dados, ativar um novo elemento e armazená-lo novamente na tag de dados no formato JSON correto. Portanto, o mesmo código pode ser usado novamente para adicionar outros elementos à matriz, se desejado. Descobri que $('#my-data-div').attr('data-namesarray', names_string);armazena corretamente a matriz, mas $('#my-data-div').data('namesarray', names_string);não 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
fonte
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
fonte
0

Este código está funcionando bem para mim.

Codifique dados com btoa

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

E então decodifique com atob

let tourData = $(this).data("json");
tourData = atob(tourData);
Hp Sharma
fonte
Infelizmente, a inicialização tem um problema Unicode e não é adequado para todos os idiomas.
AhmadJavadiNejad