Przechowuj obiekt JSON w atrybucie danych w HTML jQuery

134

Przechowuję dane stosując data-podejście w tagu HTML w następujący sposób:

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

Następnie pobieram dane w takim wywołaniu zwrotnym:

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

To działa dobrze. Utknąłem na tym, że próbuję zapisać obiekt zamiast tylko jednej z jego właściwości. Próbowałem to zrobić:

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

Następnie próbowałem uzyskać dostęp do właściwości nazwy w następujący sposób:

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

Dziennik mi mówi undefined. Wygląda więc na to, że mogę przechowywać proste ciągi w data-atrybutach, ale nie mogę przechowywać obiektów JSON ...

Próbowałem też użyć tego dzieciaka składni bez powodzenia:

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

Masz jakiś pomysł, jak zapisać rzeczywisty obiekt w tagu HTML przy użyciu tego data-podejścia?

zumzum
źródło

Odpowiedzi:

140

zamiast osadzać go w tekście, po prostu użyj $('#myElement').data('key',jsonObject);

tak naprawdę nie będzie przechowywany w html, ale jeśli używasz jquery.data, wszystko to i tak jest abstrakcyjne.

Aby odzyskać JSON , nie analizuj go , po prostu zadzwoń:

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

Jeśli otrzymujesz [Object Object]zamiast bezpośredniego JSON, po prostu uzyskaj dostęp do JSON za pomocą klucza danych:

var getBackMyJSON = $('#myElement').data('key').key;
nathan gonzalez
źródło
1
Tak więc podejście do danych pozwala mi przechowywać wartość dla każdego przycisku usuwania (każdy przycisk otrzymuje inny obiekt json ...), który mam w tabeli, umieszczając tag hmtl, jak pokazano powyżej. Czy to, co sugerujesz, pozwoli mi skojarzyć każdy obiekt z odpowiednim przyciskiem usuwania? Jak miałbym to zrobić, jak użyłbym $ ('# myElement'). w ten sam sposób? Przepraszam, nie mam w tym doświadczenia. Dzięki
zumzum
Skończyło się na przypisaniu indeksu do każdego przycisku html: <td> <button class = 'delete' data-index = '"+ i +"'> Delete </button> </td> i przechowywanie tablicy obiektów JSON w zmiennej $ objects. Następnie po kliknięciu przycisku patrzę na indeks przycisku, wykonując: var buttonIndex = $ (this) .data ('index'); a następnie otrzymuję odpowiedni obiekt z wcześniej zapisanego w ten sposób: $ objects [buttonIndex]. To działa dobrze, ale nie jestem pewien, czy jest to właściwy sposób. Dziekuję za odpowiedź!
zumzum
Jeśli pole zawiera kod JSON z kodowania PHP, możesz po prostu zrobić to: htmlspecialchars(json_encode($e))(pomysł z komentarzy Nicolasa ).
CPHPython,
w pierwszym przykładzie, czy jsonObjectmusi być poddane stringifikacji? edytuj: na wypadek, gdyby to pomogło komuś innemu, właśnie znalazłem odpowiedź na to pytanie tutaj: stackoverflow.com/a/42864472 "You don't need to stringify objects to store them using jQuery.data()"
user1063287
154

Właściwie twój ostatni przykład:

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

wydaje się, że działa dobrze (patrz http://jsfiddle.net/GlauberRocha/Q6kKU/ ).

Fajną rzeczą jest to, że ciąg znaków w atrybucie data jest automatycznie konwertowany na obiekt JavaScript. Nie widzę żadnej wady w tym podejściu, wręcz przeciwnie! Jeden atrybut wystarczy do przechowywania całego zestawu danych, gotowych do użycia w JavaScript poprzez właściwości obiektu.

(Uwaga: aby atrybutom danych automatycznie nadawano typ Object zamiast String, należy zachować ostrożność przy zapisywaniu poprawnego formatu JSON, w szczególności w celu ujęcia nazw kluczy w podwójne cudzysłowy).

Nicolas Le Thierry d'Ennequin
źródło
20
Jeśli to pomoże nikogo, oto jak uzyskać dostęp do powyższego: $('div').data('foobar').foo. api.jquery.com/data
Gary,
5
@GlauberRocha, A co jeśli dane zawierają pojedynczy cytat? 'nie działa dla mnie, gdy ja echo json_encode($array)z php. Ponieważ kończy wartość atrybutu pojedynczym cudzysłowem. Wszelkie sugestie, z wyjątkiem ręcznego usuwania pojedynczego cudzysłowu z tablicy.?
Ravi Dhoriya
1
@ Log1c ツ Tylko pomysł: spróbuj zakodować swój „as &amp;quot;(encja HTML z podwójną ucieczką), aby była renderowana w źródle jako„. Ale może właśnie tego chcesz uniknąć, mówiąc „unikanie pojedynczych cytatów ręcznie” ...
Nicolas Le Thierry d'Ennequin
2
@GlauberRocha dzięki za odpowiedź. Rozwiązałem to używając tej samej sztuczki. Użyłem htmlspecialchars () [ php.net/manual/en/function.htmlspecialchars.php] . To rozwiązane. :)
Ravi Dhoriya ツ
1
Przy użyciu tej metody napotkałem problemy, gdy jedną z właściwości obiektu był ciąg znaków zawierający pojedynczy cudzysłów. Atrybut data kończy się pierwszym napotkanym cudzysłowem, a ponieważ nie jest to prawidłowy format JSON, jest interpretowany jako ciąg. Może być możliwe zakodowanie ciągu, ale stwierdziłem, że najłatwiejszym rozwiązaniem jest użycie wielu atrybutów danych.
Jon Hulka
43

Tak to u mnie zadziałało.

Obiekt

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

Zestaw

Zakoduj obiekt z ograniczeniami za pomocą metody encodeURIComponent () i ustaw jako atrybut:

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

Dostać

Aby uzyskać wartość jako obiekt, przeanalizuj zdekodowaną wartość atrybutu za pomocą decodeURIComponent () :

var data_str = $("div#mydiv").attr("data-hero");
var my_object = JSON.parse(decodeURIComponent(data_str));
Sathvik reddy Gaddam
źródło
14

Wiele problemów z przechowywaniem serializowanych danych można rozwiązać, konwertując serializowany ciąg na base64 .

Ciąg base64 można zaakceptować prawie wszędzie bez problemu.

Spojrzeć na:

WindowOrWorkerGlobalScope.btoa()Metoda tworzy base-64 zakodowany ciąg ASCII od obiektu String, w którym każdy znak w ciągu jest traktowany jako bajt danych binarnych.

WindowOrWorkerGlobalScope.atob()Funkcja dekodowania ciąg danych, które zostały zaszyfrowane za pomocą bazowym 64 kodowania.

Konwertuj na / z w razie potrzeby.

Dan
źródło
Działa to naprawdę dobrze przy przekazywaniu złożonych obiektów do atrybutów.
baacke
Niestety, boot ma problem z Unicode i nie jest odpowiedni dla wszystkich języków.
AhmadJavadiNejad
Do użytku w przeglądarcewindow.btoa
Henry
1
Ta metoda jest dość kuloodporna IMO. Jednak po pobraniu i odkodowaniu ciągu base64 masz serializowany kod JSON. Potrzebujesz więc go, JSON.parsezanim będziesz mógł użyć wyniku jako obiektu.
Henry
13

U mnie tak to działa, ponieważ muszę to przechowywać w szablonie ...

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

// Later
var dataObj = $('div').data('dataObj'); // jQuery automatically unescape it
molokoloco
źródło
1
dzięki za udostępnienie… dokładnie tego, czego szukałem… ciągle otrzymywałem [Object Object], gdy próbowałem przeanalizować zaakceptowaną odpowiedź.
GreaterKing
@greaterKing nie analizujesz JSON z zaakceptowanej odpowiedzi, po prostu uzyskujesz do niego dostęp za pomocą klucza, który jest taki sam jak nazwa danych, więc jeśli masz np. $('body').data('myData', { h: "hello", w: "world" })_____________________________________________________________________________________________, otrzymasz swój obiekt JSON przez$('body').data().myData
jave.web
Aby uprościć, możesz to zrobić '<div data-dataObj=\''+ JSON.stringify(dataObj) +'\'></div>'. To są pojedyncze cudzysłowy, początek i koniec są po prostu unikane, więc byłoby to samo, co posiadanie'{"some":"thing"}'
IamFace
1
@IamFace - replace()dotyczy możliwości pojawiania się pojedynczych cudzysłowów w danych json, co jest całkowicie możliwe.
billynoah
3

Sztuczka polegała na dodaniu podwójnych cudzysłowów wokół kluczy i wartości . Jeśli używasz funkcji PHP, takiej jak json_encode, poda ci ciąg zakodowany w formacie JSON i pomysł, jak poprawnie zakodować swój.

jQuery('#elm-id').data('datakey') zwróci obiekt ciągu, jeśli ciąg jest poprawnie zakodowany jako json.

Zgodnie z dokumentacją jQuery: ( http://api.jquery.com/jquery.parsejson/ )

Przekazanie zniekształconego ciągu JSON powoduje zgłoszenie wyjątku JavaScript. Na przykład wszystkie poniższe są nieprawidłowe ciągi JSON:

  1. "{test: 1}"( testnie ma wokół niego podwójnych cudzysłowów).
  2. "{'test': 1}"( 'test'używa pojedynczych cudzysłowów zamiast podwójnych cudzysłowów).
  3. "'test'"( 'test'używa pojedynczych cudzysłowów zamiast podwójnych cudzysłowów).
  4. ".1"(liczba musi zaczynać się od cyfry; "0.1"byłaby ważna).
  5. "undefined"( undefinednie może być reprezentowany w ciągu JSON; nulljednak może być).
  6. "NaN"( NaNnie może być reprezentowany w ciągu JSON; bezpośrednia reprezentacja Infinity to również n
George Donev
źródło
2

Połącz użycie window.btoai window.atobrazem z JSON.stringifyi JSON.parse.

- Działa to w przypadku ciągów zawierających pojedyncze cudzysłowy

Kodowanie danych:

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

Dekodowanie danych:

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

Oto przykład, w jaki sposób dane są konstruowane i dekodowane później za pomocą zdarzenia kliknięcia.

Skonstruuj HTML i zakoduj dane:

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

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

Dekoduj dane w module obsługi zdarzeń kliknięcia:

$("#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
źródło
0

Użycie udokumentowanej składni jquery .data (obj) umożliwia przechowywanie obiektu w elemencie DOM. Sprawdzanie elementu nie pokaże data-atrybutu, ponieważ nie określono klucza dla wartości obiektu. Jednak do danych w obiekcie można się odwoływać za pomocą klucza z .data("foo")lub można zwrócić cały obiekt za pomocą .data().

Zakładając więc, że skonfigurujesz pętlę i 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
źródło
0

Z jakiegoś powodu zaakceptowana odpowiedź działała dla mnie tylko wtedy, gdy była używana raz na stronie, ale w moim przypadku próbowałem zapisać dane na wielu elementach na stronie i dane zostały w jakiś sposób utracone na wszystkich poza pierwszym elementem.

Alternatywnie, zapisałem dane do domeny i przeanalizowałem je z powrotem, gdy było to potrzebne. Być może jest mniej wydajna, ale działała dobrze w moim celu, ponieważ naprawdę tworzę prototypy danych i nie piszę ich do produkcji.

Aby zapisać dane, których użyłem:

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

Odczytanie danych jest takie samo, jak zaakceptowana odpowiedź, a mianowicie:

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

Zrobienie tego w ten sposób sprawiło, że dane pojawiły się w dom, gdybym miał sprawdzić element za pomocą debugera Chrome.

Shane E.
źródło
0

.data()działa idealnie w większości przypadków. Jedyny raz, kiedy miałem problem, miał miejsce, gdy sam ciąg JSON miał pojedynczy cudzysłów. Nie mogłem znaleźć łatwego sposobu na obejście tego, więc uciekłem się do tego podejścia (używam Coldfusion jako języka serwera):

    <!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
źródło
0

Dla przypomnienia, stwierdziłem, że działa następujący kod. Umożliwia pobranie tablicy ze znacznika danych, przekazanie nowego elementu i zapisanie go z powrotem w znaczniku danych we właściwym formacie JSON. W razie potrzeby ten sam kod może być zatem ponownie użyty do dodania kolejnych elementów do tablicy. Okazało się, że $('#my-data-div').attr('data-namesarray', names_string);poprawnie przechowuje tablicę, ale $('#my-data-div').data('namesarray', names_string);nie działa.

<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
źródło
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
źródło
0

Ten kod działa dobrze dla mnie.

Koduj dane za pomocą btoa

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

A następnie dekoduj go za pomocą atob

let tourData = $(this).data("json");
tourData = atob(tourData);
Hp Sharma
źródło
Niestety, boot ma problem z Unicode i nie jest odpowiedni dla wszystkich języków.
AhmadJavadiNejad