Зберігайте об’єкт 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.