web-dev-qa-db-ja.com

jQuery Data()APIを使用してデータ属性を設定できません

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()呼び出しは正常に機能し、アラートダイアログに「Old Text」というテキストが表示されます。ただし、data-helptext属性を「Testing 123」に設定する呼び出しは機能しません。 「古いテキスト」は、まだ属性の現在の値です。

Data()の呼び出しを間違って使用していますか?私はこれをウェブで調べましたが、何が間違っているのかわかりません。

HTMLマークアップは次のとおりです。

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

.data() documentation に記載されています

データ属性は、データプロパティに最初にアクセスしたときに取得され、アクセスまたは変更されなくなります(すべてのデータ値はjQueryに内部的に格納されます)

これは jQuery $ .fn.data()への変更が対応するhtml 5 data- *属性を更新しない理由?

以下の私の最初の答えのデモはもう機能しないようです。

更新された回答

繰り返しますが、 .data() documentation

ダッシュが埋め込まれた属性の処理は、jQuery 1.6でW3C HTML5仕様に準拠するように変更されました。

したがって、<div data-role="page"></div>の場合、次のことが当てはまります$('div').data('role') === 'page'

$('div').data('data-role')は過去に機能していたと確信していますが、もはやそうではないようです。コンソールを開く必要はなく、HTMLにログを記録するより優れたショーケースを作成し、マルチハイフンの追加の例をcamelCase data- attributes 変換に追加しました。

更新されたデモ(2015-07-25)

jQuery Data vs 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 DevToolsConsoleを使用してDOMを検査すると、$('#foo').data('helptext', 'Testing 123');does notConsoleに表示されるように値を更新しますが、$('#foo').attr('data-helptext', 'Testing 123');は更新します。

239
andyb

私は深刻な問題を抱えていました

.data('property', value);

data-property属性を設定していませんでした。

JQueryの .attr() の使用を開始しました:

一致した要素のセットの最初の要素の属性の値を取得するか、一致したすべての要素に1つ以上の属性を設定します。

.attr('property', value)

値を設定し、

.attr('property')

値を取得します。

今ではうまくいきます!

34

@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は更新されません)

「データ」属性のポイントは、値を要素にバインド(または「リンク」)することです。アクションを要素にバインドするonclick="alert('do_something')"属性に非常に似ています...テキストは役に立たないので、要素をクリックしたときにアクションが機能するようにします。

データまたはアクションが要素にバインドされると、アプリケーション(JavaScript)が使用するものであるため、データまたはメソッドのみを更新し、HTMLを更新する必要はありません通常*があります。パフォーマンスに関しては、とにかくHTMLも更新する理由がわかりません。html属性は表示されません(Firebugまたは他のコンソールを除く)。

あなたがそれについて考えることを望むかもしれない1つの方法:HTMLは(属性とともに)単なるテキストです。 JavaScriptで使用されるデータ、関数、オブジェクトなどは、別のプレーンに存在します。 JavaScriptがそうするように指示された場合にのみ、HTMLテキストを読み取りまたは更新しますが、JavaScriptで作成するすべてのデータと機能は、Firebug(または他の)コンソールに表示されるHTMLテキスト/属性とは完全に分離して動作します。

* 通常に重点を置きます。HTMLを別のページにロードするHTMLを保存およびエクスポートする必要がある場合(たとえば、ある種のマイクロ形式/データ対応テキストエディター)、次に、HTMLも更新する必要があります。

8
Frank Forte

私にも同じことが起こりました。それが判明した

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

書き込み不可能なオブジェクトを提供します。私はそれを使って解決しました:

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

それ以降、dataは標準の書き込み可能なJSオブジェクトでした。

6
Nico

引用を引用するには:

データ属性は、データプロパティへの最初のアクセス時に取得され、その後アクセスまたは変更されなくなります(すべてのデータ値はjQueryに内部的に格納されます)。

.data()-jQuery Documentiation

この(率直に言ってodd)の制限は、.data()の使用のみに制限されていることに注意してください。

ソリューション?代わりに.attrを使用してください。

もちろん、あなたの何人かは専用の方法を使用しないことに不快感を感じるかもしれません。次のシナリオを検討してください。

  • 「標準」が更新され、カスタム属性のデータ部分が不要になりました/置き換えられました

常識-なぜすでに確立された属性をそのように変更するのですか? classgroupに名前変更され、ididentifierに変更されることを想像してください。インターネットが壊れます。

そして、それでも、Javascript自体にはこれを修正する機能があります-そして、もちろん、それはHTMLとの悪名高い非互換性にもかかわらず、REGEX(およびさまざまな同様のメソッド)は、この新しい神話の「標準」にあなたの属性の名前を迅速に変更できます.

TL; DR

alert($(targetField).attr("data-helptext"));
3
Super Cat

前述のように、.data()メソッドはdata-属性の値を実際に設定することも、data-属性が変更された場合に更新された値を読み取ることもありません。

私の解決策は、属性の現在の値に実際に対応する.realData()メソッドでjQueryを拡張することでした:

// 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()を使用することで、意図された動作をより明確にすることができます。

1
Yarin

同じ問題がありました。 .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]);
    }
}

編集:2017年5月1日

組み込みのメソッドを使用して正しいデータを取得できない場合がまだあることがわかったため、現在使用しているのは次のとおりです。

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;
};
0
Matthew Pautzke