Невозможно установить атрибут данных с помощью API jQuery Data () - PullRequest
131 голосов
/ 26 июля 2011

У меня есть следующее поле в представлении MVC:

@Html.TextBoxFor(model => model.Course.Title, new { data_helptext = "Old Text" })</span>

В отдельном js-файле я хочу установить для атрибута data-helptext строковое значение. Вот мой код:

alert($(targetField).data("helptext"));

$(targetField).data("helptext", "Testing 123");

Вызов alert() работает нормально, в диалоговом окне с предупреждением отображается текст «Старый текст». Однако вызов для установки атрибута data-helptext на «Тестирование 123» не работает. «Старый текст» по-прежнему является текущим значением атрибута.

Я неправильно использую вызов data ()? Я посмотрел это в Интернете, и я не вижу, что я делаю неправильно.

Вот разметка HTML:

<input data-helptext="Old Text" id="Course_Title" name="Course.Title" type="text" value="" />

Ответы [ 7 ]

239 голосов
/ 26 июля 2011

Упоминается в документации .data()

Атрибуты данных извлекаются при первом обращении к свойству данных, а затем более не доступны или не изменены(все значения данных затем сохраняются внутри в jQuery)

Это также было рассмотрено на Почему изменения в jQuery $ .fn.data () не обновляют соответствующие данные html 5 data- *Атрибуты?

Демонстрация моего первоначального ответа ниже, похоже, больше не работает.

Обновленный ответ

Опять же, из.data() документация

Обработка атрибутов со встроенными тире была изменена в jQuery 1.6 для соответствия спецификации W3C HTML5.

Итакдля <div data-role="page"></div> верно следующее $('div').data('role') === 'page'

Я вполне уверен, что $('div').data('data-role') работал в прошлом, но, похоже, это уже не так.Я создал лучшую витрину, которая регистрирует в HTML, вместо того, чтобы открывать консоль, и добавил дополнительный пример преобразования нескольких дефисов в camelCase data-attribute .

Обновленная демоверсия (2015-07-25)

См. Также Данные jQuery против Attr?

HTML

<div id="changeMe" data-key="luke" data-another-key="vader"></div>
<a href="#" id="changeData"></a>
<table id="log">
    <tr><th>Setter</th><th>Getter</th><th>Result of calling getter</th><th>Notes</th></tr>
</table>

JavaScript (jQuery 1.6.2 +)

var $changeMe = $('#changeMe');
var $log = $('#log');

var logger;
(logger = function(setter, getter, note) {
    note = note || '';
    eval('$changeMe' + setter);
    var result = eval('$changeMe' + getter);
    $log.append('<tr><td><code>' + setter + '</code></td><td><code>' + getter + '</code></td><td>' + result + '</td><td>' + note + '</td></tr>');
})('', ".data('key')", "Initial value");

$('#changeData').click(function() {
    // set data-key to new value
    logger(".data('key', 'leia')", ".data('key')", "expect leia on jQuery node object but DOM stays as luke");
    // try and set data-key via .attr and get via some methods
    logger(".attr('data-key', 'yoda')", ".data('key')", "expect leia (still) on jQuery object but DOM now yoda");
    logger("", ".attr('key')", "expect undefined (no attr <code>key</code>)");
    logger("", ".attr('data-key')", "expect yoda in DOM and on jQuery object");

    // bonus points
    logger('', ".data('data-key')", "expect undefined (cannot get via this method)");
    logger(".data('anotherKey')", ".data('anotherKey')", "jQuery 1.6+ get multi hyphen <code>data-another-key</code>");
    logger(".data('another-key')", ".data('another-key')", "jQuery < 1.6 get multi hyphen <code>data-another-key</code> (also supported in jQuery 1.6+)");

    return false;
});

$('#changeData').click();

Старая демоверсия


Оригинальный ответ

Для этого HTML:

<div id="foo" data-helptext="bar"></div>
<a href="#" id="changeData">change data value</a>

и этого JavaScript (с jQuery 1.6.2)

console.log($('#foo').data('helptext'));

$('#changeData').click(function() {
    $('#foo').data('helptext', 'Testing 123');
//  $('#foo').attr('data-helptext', 'Testing 123');
    console.log($('#foo').data('data-helptext'));
    return false;
});

См. Демонстрацию

Использование Chrome DevTools Консоли для проверки DOM, $('#foo').data('helptext', 'Testing 123'); не не обновляет значение, как видно на консоли , но $('#foo').attr('data-helptext', 'Testing 123'); делает.

34 голосов
/ 24 сентября 2014

У меня были серьезные проблемы с

.data('property', value);

Не был установлен атрибут data-property.

Начато с помощью jQuery's .attr():

Получить значение атрибута для первого элемента в наборе сопоставленные элементы или установите один или несколько атрибутов для каждого сопоставленного элемент.

.attr('property', value)

для установки значения и

.attr('property')

для получения значения.

Теперь это просто работает!

8 голосов
/ 13 сентября 2014

@ Принятый ответ andyb содержит небольшую ошибку.В дополнение к моему комментарию к его сообщению выше ...

Для этого HTML:

<div id="foo" data-helptext="bar"></div>
<a href="#" id="changeData">change data value</a>

Вам необходимо получить доступ к атрибуту, как это:

$('#foo').attr('data-helptext', 'Testing 123');

, ноМетод данных, подобный следующему:

$('#foo').data('helptext', 'Testing 123');

Исправление, приведенное выше для метода .data (), предотвратит "неопределенное", и значение данных будет обновлено (в то время как HTML не будет)

смысл атрибута «data» - связать (или «связать») значение с элементом.Очень похоже на атрибут onclick="alert('do_something')", который связывает действие с элементом ... текст бесполезен, вы просто хотите, чтобы действие работало, когда они щелкают по элементу.

Как только данные или действие связаны сдля элемента обычно * нет необходимости обновлять HTML, только данные или метод, поскольку именно это будет использовать ваше приложение (JavaScript).С точки зрения производительности, я не понимаю, почему вы все равно захотите обновить HTML, никто не видит атрибут html (кроме Firebug или других консолей).

Один из способов подумать об этом:HTML (вместе с атрибутами) - это просто текст.Данные, функции, объекты и т. Д., Используемые JavaScript, существуют в отдельной плоскости.Только когда JavaScript получит указание сделать это, он будет читать или обновлять текст HTML, но все данные и функции, которые вы создаете с помощью JavaScript, действуют совершенно отдельно от текста / атрибутов HTML, которые вы видите в своей консоли Firebug (или другой).

* Я сделал акцент на обычно , потому что если у вас есть случай, когда вам нужно сохранить и экспортировать HTML (например, какой-нибудь текстовый редактор с поддержкой микроформатов / данных), где HTML будет загружаться свежимна другой странице, возможно, вам также понадобится обновить HTML.

6 голосов
/ 02 декабря 2013

случилось то же самое со мной.Оказывается, что

var data = $("#myObject").data();

дает вам недоступный для записи объект.Я решил это, используя:

var data = $.extend({}, $("#myObject").data());

И с тех пор data был стандартным, доступным для записи объектом JS.

3 голосов
/ 25 января 2015

Чтобы процитировать цитату:

Атрибуты данных извлекаются при первом обращении к свойству данных, а затем более не доступны или не изменены (все значения данных затем сохраняются внутри в jQuery.).

.data() - jQuery Documentiation

Обратите внимание, что это (откровенно нечетное ) ограничение запрещено только при использовании.data().

Решение?Вместо этого используйте .attr.

Конечно, некоторые из вас могут чувствовать себя некомфортно из-за того, что не используют его специальный метод.Рассмотрим следующий сценарий:

  • «Стандарт» обновляется, так что часть данных пользовательских атрибутов больше не требуется / заменяется

Здравый смысл - зачемони изменяют уже установленный атрибут, как это?Только представьте, class начинают переименовывать в группу и id в идентификатор .Интернет сломается.

И даже в этом случае сам Javascript способен это исправить - и, конечно, несмотря на печально известную несовместимость с HTML, REGEX (и множество подобных методов) может быстро переименовать ваши атрибуты вэтот новый мифический «стандарт».

TL; DR

alert($(targetField).attr("data-helptext"));
1 голос
/ 15 октября 2018

Как уже упоминалось, метод .data() на самом деле не устанавливает значение атрибута data- и не считывает обновленные значения, если атрибут data- изменяется.

Мое решение заключалось в расширении jQuery с помощью метода .realData(), который фактически соответствует текущему значению атрибута:

// Alternative to .data() that updates data- attributes, and reads their current value.
(function($){
  $.fn.realData = function(name,value) {
      if (value === undefined) {
        return $(this).attr('data-'+name);
      } else {
        $(this).attr('data-'+name,value);
      }
  };
})(jQuery);

ПРИМЕЧАНИЕ: Конечно, вы можете просто использовать .attr(), но по моему опыту, большинство разработчиков (иначе меня) допускают ошибку, рассматривая .attr() и .data() как взаимозаменяемые, и часто заменяют одно для другого, не задумываясь. Это может работать большую часть времени, но это отличный способ сообщить об ошибках, особенно при работе с любым видом динамического связывания данных. Таким образом, используя .realData(), я могу более четко рассказать о предполагаемом поведении.

0 голосов
/ 24 ноября 2015

Была такая же проблема. Поскольку вы все еще можете получать данные с помощью метода .data (), вам нужно только найти способ записи в элементы. Это вспомогательный метод, который я использую. Как и большинство людей сказали, вам придется использовать .attr. У меня есть замена любого _ с - как я знаю, это делает это. Я не знаю ни о каких других символах, которые он заменяет ... однако я не исследовал это.

function ExtendElementData(element, object){
    //element is what you want to set data on
    //object is a hash/js-object
    var keys = Object.keys(object);
    for (var i = 0; i < keys.length; i++){
        var key = keys[i];
        $(element).attr('data-'+key.replace("_", "-"), object[key]);
    }
}

РЕДАКТИРОВАТЬ: 5/1/2017

Я обнаружил, что все еще были случаи, когда вы не могли получить правильные данные, используя встроенные методы, поэтому сейчас я использую следующее:

function setDomData(element, object){
    //object is a hash

    var keys = Object.keys(object);
    for (var i = 0; i < keys.length; i++){
        var key = keys[i];
        $(element).attr('data-'+key.replace("_", "-"), object[key]);
    }
};

function getDomData(element, key){
    var domObject = $(element).get(0);
    var attKeys = Object.keys(domObject.attributes);

    var values = null;
    if (key != null){
        values = $(element).attr('data-' + key);
    } else {
        values = {};

        var keys = [];
        for (var i = 0; i < attKeys.length; i++) {
            keys.push(domObject.attributes[attKeys[i]]);
        }

        for (var i = 0; i < keys.length; i++){
            if(!keys[i].match(/data-.*/)){
                values[keys[i]] = $(element).attr(keys[i]);
            }
        }
    }
    return values;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...