Зберігайте об’єкт JSON в атрибуті даних у HTML jQuery


134

Я зберігаю дані за допомогою data-підходу в тезі HTML так:

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

Потім я отримую дані у зворотній виклик так:

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

Це прекрасно працює. Те, про що я застряг, намагається зберегти об’єкт, а не лише одну з властивостей його. Я намагався це зробити:

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

Тоді я спробував отримати доступ до властивості імені так:

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

Журнал мені підказує undefined. Тож здається, що я можу зберігати прості рядки в data-атрибутах, але я не можу зберігати об’єкти JSON ...

Я також намагався невдало використовувати цю дитину синтаксису:

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

Будь-яка ідея, як зберігати фактичний об’єкт у тезі HTML, використовуючи data-підхід?

Відповіді:


140

замість того, щоб вбудовувати його в текст, просто використовуйте $('#myElement').data('key',jsonObject);

він насправді не зберігатиметься в html, але якщо ви використовуєте jquery.data, все, що все-таки абстрагується.

Щоб повернути JSON , не розбирайте його , просто зателефонуйте:

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

Якщо ви отримуєте [Object Object]замість прямого JSON, просто перейдіть до свого JSON за допомогою ключа даних:

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

1
Тож використання підходу до даних дозволяє мені зберігати значення для кожної кнопки видалення (кожна кнопка отримує інший об’єкт json ...) Я маю в таблиці, вводячи тег hmtl, як я показав вище. Чи ви пропонуєте дозволити мені пов’язати кожен об'єкт із відповідною кнопкою видалення? Як би це зробити, як би я використовував $ ('# myElement'). таким же чином? Вибачте, я цього не маю. Дякую
zumzum

Тому я закінчив присвоювати індекс кожній кнопці html: <td> <button class = 'delete' data-index = '"+ i +"'> Видалити </button> </td> та зберігати масив JSON-об'єктів у змінній $ об’єктів. Потім при натисканні кнопки я дивлюся на індекс кнопки, виконуючи: var buttonIndex = $ (this) .data ('index'); а потім я отримую відповідний об'єкт із раніше збереженого так: $ об’єкти [buttonIndex]. Це прекрасно працює, не впевнений, чи правильно це зробити. Дякуємо за ваш відгук!
zumzum

Якщо поле містить JSON з кодування PHP, ви можете просто зробити це замість цього: htmlspecialchars(json_encode($e))(ідея від коментарів Nicolas відповіді ).
CPHPython

у першому прикладі, чи jsonObjectпотрібно впорядкувати їх? Редагування: в разі , якщо це допомагає хто - то інший, я тільки що знайшов відповідь на це питання тут: stackoverflow.com/a/42864472 "You don't need to stringify objects to store them using jQuery.data()"
user1063287

154

Власне, ваш останній приклад:

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

здається, працює добре (див. http://jsfiddle.net/GlauberRocha/Q6kKU/ ).

Приємно те, що рядок у атрибуті data автоматично перетворюється на об’єкт JavaScript. Я не бачу жодного недоліку в такому підході, навпаки! Одного атрибуту достатньо для зберігання цілого набору даних, готових до використання в JavaScript через властивості об'єкта.

.


20
Якщо це допомагає будь-кому, ось як отримати доступ до вище: $('div').data('foobar').foo. api.jquery.com/data
Гері

5
@GlauberRocha, що робити, якщо дані містять єдину цитату? 'не працює для мене, поки я echo json_encode($array)з PHP. Оскільки воно припинить значення атрибута одиничною цитатою. Будь-яка пропозиція, крім уникнення єдиної цитати вручну з масиву.
Раві Дхорія ツ

1
@ Log1c ツ Просто ідея: спробуйте кодувати своє "як" &amp;quot;(подвійний HTML-об'єкт), щоб він відображався у вашому джерелі як & quot ;. Але, можливо, саме такого, чого ви хочете уникнути, сказавши "втечу єдиної цитати вручну" ...
Ніколас Ле Тьєррі д'Енненекен

2
@GlauberRocha дякую за відповідь. Я вирішив це за допомогою тієї ж хитрості. Я використовував htmlspecialchars () [ php.net/manual/en/function.htmlspecialchars.php] . Це вирішило. :)
Раві Дхорія ツ

1
Я зіткнувся з проблемою, використовуючи цей метод, коли одним із властивостей об'єкта була рядок, що містить одну цитату. Атрибут даних закінчується першою зустріченою цитатою, і оскільки він не є дійсним JSON, він інтерпретується як рядок. Можливо, можливо, кодувати рядок, але я знайшов, що найпростішим рішенням було просто використовувати декілька атрибутів даних.
Джон Хулка

43

Ось як це працювало для мене.

Об'єкт

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

Встановити

Зашифруйте об'єкт пошарпаного об'єкта encodeURIComponent () і встановіть як атрибут:

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

Отримайте

Щоб отримати значення як об'єкт, проаналізуйте розшифроване, за допомогою decodeURIComponent () значення атрибута:

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

14

Багато проблем зі збереженням серіалізованих даних можна вирішити шляхом перетворення серіалізованої рядки в base64 .

Рядок base64 можна приймати майже де завгодно, без суєти.

Подивись на:

WindowOrWorkerGlobalScope.btoa()Метод створює базову 64 кодований ASCII рядок з строкового об'єкта , в якому кожен символ в рядку трактуються як байти двійкових даних.

WindowOrWorkerGlobalScope.atob()Функція декодує рядок даних , які були закодовані з використанням базових 64 кодування.

Перетворити на / із необхідності.


Це дуже добре працює для передачі складних Об'єктів в атрибути.
baacke

На жаль, завантаження має проблему Unicode і підходить не для всіх мов.
AhmadJavadiNejad

Для використання в браузеріwindow.btoa
Генрі

1
Цей метод є досить куленепроникним IMO. Однак, як тільки ви отримаєте та скасуєте кодування своєї базової 64, ви серіалізували JSON. Тому вам потрібна миша, JSON.parseперш ніж ви зможете використовувати результат як об’єкт.
Генрі

13

Для мене це працює так, як мені потрібно зберігати його в шаблоні ...

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

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

1
дякую за те, що поділився ... саме те, що я шукав ... продовжував отримувати [Object Object] при спробі розбору прийнятої відповіді.
більшийКорін

@greaterKing ви не розбираєте JSON з прийнятої відповіді, ви просто отримуєте доступ до нього через ключ, який відповідає імені даних, тому, якщо у вас є, наприклад, $('body').data('myData', { h: "hello", w: "world" })_____________________________________________________________________________________________, ви отримаєте свій об'єкт JSON від$('body').data().myData
jave.web

Для спрощення можна зробити '<div data-dataObj=\''+ JSON.stringify(dataObj) +'\'></div>'. Це все єдині цитати, початок і кінець просто уникли, тож це було б те саме, що мати'{"some":"thing"}'
IamFace

1
@IamFace - replace()вирішує можливість появи єдиних лапок у даних json, що цілком можливо.
billynoah

3

Трюком для мене було додати подвійні лапки навколо ключів та значень . Якщо ви використовуєте функцію PHP, як-от, json_encodeви дасте рядок, кодований JSON, та ідею, як правильно кодувати свою.

jQuery('#elm-id').data('datakey') поверне об'єкт рядка, якщо рядок правильно кодований як json.

Відповідно до документації jQuery: ( http://api.jquery.com/jquery.parsejson/ )

Передача в неправильно сформованому рядку JSON призводить до викидання виключення JavaScript. Наприклад, наведені нижче всі недійсні рядки JSON:

  1. "{test: 1}"( testне має подвійних лапок навколо).
  2. "{'test': 1}"( 'test'використовується одинарні лапки замість подвійних лапок).
  3. "'test'"( 'test'використовується одинарні лапки замість подвійних лапок).
  4. ".1"(число повинно починатися з цифри; "0.1"було б дійсним).
  5. "undefined"( undefinedне може бути представлено у рядку JSON; nullпроте, може бути).
  6. "NaN"( NaNне може бути представлений у рядку JSON; пряме подання Infinity також n

2

Поєднайте використання window.btoaта window.atobразом із JSON.stringifyта JSON.parse.

- Це працює для рядків, що містять одиничні лапки

Кодування даних:

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

Розшифровка даних:

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

Ось приклад того, як дані будуються та декодуються пізніше за допомогою події клацання.

Побудуйте html та кодуйте дані:

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

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

Розшифруйте дані в обробці подій клацання:

$("#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"] 
}

0

Використання задокументованого синтаксису jquery .data (obj) дозволяє зберігати об’єкт на елементі DOM. Перевірка елемента не відобразить data-атрибут, оскільки для значення об'єкта не вказаний ключ. Однак, дані всередині об'єкта можуть бути посилані ключем .data("foo")або весь об'єкт можна повернути за допомогою .data().

Тож припустимо, що ви налаштували цикл і 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" }

0

Чомусь прийнята відповідь працювала для мене лише в тому випадку, якщо її використовували один раз на сторінці, але в моєму випадку я намагався зберегти дані про багато елементів на сторінці, і дані були якимось чином втрачені на всіх, окрім першого елемента.

Як альтернатива, я закінчив записувати дані до дому та аналізувати їх, коли потрібно. Можливо, це менш ефективно, але добре працював за своїм призначенням, бо я справді прототипував дані і не пишу цього для виробництва.

Для збереження використаних даних:

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

Потім прочитати дані назад те саме, що прийнято відповідь, а саме:

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

Це робило це також, коли дані з'являлися у домі, якщо я хотів би перевірити елемент за допомогою налагоджувача Chrome.


0

.data()прекрасно працює в більшості випадків. Єдиний раз, коли у мене виникли проблеми, коли в рядку JSON сама була одна цитата. Я не міг знайти жодного легкого способу пройти це, настільки вдався до цього підходу (я використовую Coldfusion як мову сервера):

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

0

Для запису я знайшов наступний код роботи. Це дає змогу отримати масив із тегу даних, натиснути новий елемент і зберегти його назад у тезі даних у правильному форматі JSON. Тому той самий код може бути використаний знову для додавання додаткових елементів до масиву, якщо потрібно. Я виявив, що $('#my-data-div').attr('data-namesarray', names_string);правильно зберігає масив, але $('#my-data-div').data('namesarray', names_string);не працює.

<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);

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...

0

Цей код добре працює для мене.

Кодуйте дані за допомогою btoa

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

А потім розшифруйте його за допомогою атобу

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

На жаль, завантаження має проблему Unicode і підходить не для всіх мов.
AhmadJavadiNejad
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.