131 votes

Impossible de définir un attribut de données à l'aide de l'API jQuery Data()

J'ai le champ suivant dans une vue MVC :

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

Dans un fichier js séparé, je veux définir l'option data-helptext à une valeur de type chaîne. Voici mon code :

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

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

Le site alert() fonctionne bien, il affiche le texte "Ancien texte" dans une boîte de dialogue d'alerte. Toutefois, l'appel visant à définir la valeur data-helptext à "Testing 123" ne fonctionne pas. L'"ancien texte" reste la valeur actuelle de l'attribut.

Est-ce que j'utilise l'appel à data() de manière incorrecte ? J'ai fait des recherches sur le web et je ne vois pas ce que je fais de mal.

Voici le balisage HTML :

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

0 votes

Le code semble correct. Aucun problème dans cette démo . Quelle version de jQuery utilisez-vous ?

0 votes

J'utilise la version 1.5.1 fournie avec le modèle de projet ASP NET MVC. Serait-il possible que je doive mettre à jour jQuery ?

0 votes

OK, ce n'est pas la version de jQuery alors. Je pensais que c'était peut-être une très vieille version. L'API data() que vous utilisez a été ajoutée dans la version 1.2.3.

239voto

andyb Points 26066

Il est mentionné dans le .data() documentation

Les attributs data- sont intégrés lors du premier accès à la propriété data et ne sont ensuite plus accessibles ou modifiés (toutes les valeurs de données sont alors stockées en interne dans jQuery).

Ce sujet a également été abordé sur Pourquoi les modifications apportées à jQuery $.fn.data() ne mettent pas à jour les attributs data-* de html 5 correspondants ?

La démo sur ma réponse originale ci-dessous ne semble plus fonctionner.

Réponse actualisée

Encore une fois, d'après le .data() documentation

Le traitement des attributs avec des tirets intégrés a été modifié dans jQuery 1.6 pour se conformer à la spécification HTML5 du W3C.

Donc pour <div data-role="page"></div> ce qui suit est vrai $('div').data('role') === 'page'

Je suis presque sûr que $('div').data('data-role') fonctionnait dans le passé, mais cela ne semble plus être le cas. J'ai créé une meilleure vitrine qui enregistre en HTML plutôt que d'avoir à ouvrir la Console et j'ai ajouté un exemple supplémentaire du passage de multi-hyphen à camelCase données - attributs conversion.

Démonstration mise à jour (2015-07-25)

Voir aussi jQuery Data ou 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();

Démo plus ancienne


Réponse originale

Pour ce HTML :

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

et ce JavaScript (avec 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;
});

Voir la démo

Utilisation de la Outils de développement de Chrome Console pour inspecter le DOM, le $('#foo').data('helptext', 'Testing 123'); n'est pas mettre à jour la valeur comme indiqué dans le Console mais $('#foo').attr('data-helptext', 'Testing 123'); fait.

1 votes

Je ne suis pas sûr de ce qui a changé, mais votre démonstration renvoie undefined dans la console de chrome.

0 votes

Alors, quel est l'intérêt pour jQuery de vous permettre de mettre un deuxième argument ? Pour mettre à jour la valeur stockée dans le cache de la variable js ?

0 votes

@gwho Je ne suis pas sûr de comprendre complètement votre question, mais je suppose que vous faites référence à la réponse originale de 2011 utilisant jQuery 1.6.2. Si c'est le cas, le fichier . data('key', 'value') méthode hace met à jour la valeur dans le cache de jQuery mais pour des raisons de performance (je suppose la mutation du DOM) le DOM lui-même n'est pas mis à jour.

35voto

Leniel Macaferi Points 38324

J'avais de sérieux problèmes avec

.data('property', value);

Il ne fixait pas le data-property attribut.

J'ai commencé à utiliser l'outil jQuery .attr() :

Obtenir la valeur d'un attribut pour le premier élément de l'ensemble des éléments correspondants ou de l'ensemble d'un élément. éléments appariés ou définir un ou plusieurs attributs pour chaque élément apparié. correspondant.

.attr('property', value)

pour définir la valeur et

.attr('property')

pour récupérer la valeur.

Maintenant, ça marche !

1 votes

Pour moi, j'ai pu modifier la propriété data avec data() mais j'ai remarqué que dans les outils du développeur, le changement n'était pas affiché, c'est pourquoi j'ai utilisé attr().

9voto

Frank forte Points 89

La réponse acceptée de @andyb a un petit bug. Suite à mon commentaire sur son post ci-dessus...

Pour ce HTML :

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

Vous devez accéder à l'attribut comme ceci :

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

mais la méthode de données comme ceci :

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

La correction ci-dessus pour la méthode .data() empêchera "undefined" et la valeur des données sera mise à jour (mais pas le HTML).

Le but de l'attribut "data" est de lier (ou de "lier") une valeur à l'élément. Très similaire à l'attribut onclick="alert('do_something')" qui lie une action à l'élément... le texte est inutile, vous voulez juste que l'action fonctionne lorsqu'ils cliquent sur l'élément.

Une fois que la donnée ou l'action est liée à l'élément, il y a généralement* il n'est pas nécessaire de mettre à jour le HTML, seulement les données ou la méthode, puisque c'est ce que votre application (JavaScript) utiliserait. Du point de vue des performances, je ne vois pas pourquoi vous voudriez également mettre à jour le HTML de toute façon, personne ne voit l'attribut html (sauf dans Firebug ou d'autres consoles).

Une façon d'y penser : Le HTML (avec les attributs) n'est que du texte. Les données, les fonctions, les objets, etc. qui sont utilisés par JavaScript existent sur un plan séparé. Ce n'est que lorsque JavaScript en reçoit l'ordre qu'il lit ou met à jour le texte HTML, mais toutes les données et fonctionnalités que vous créez avec JavaScript agissent de manière totalement distincte du texte/attributs HTML que vous voyez dans votre console Firebug (ou autre).

*Je mets l'accent sur généralement parce que si vous avez un cas où vous devez préserver et exporter du HTML (par exemple une sorte d'éditeur de texte micro format/data aware) où le HTML se chargera fraîchement sur une autre page, alors peut-être avez-vous besoin que le HTML soit mis à jour aussi.

0 votes

Merci. Cela m'a aidé, parmi toutes les autres réponses avec des exemples incorrects ! Le site data en attr('data-helptext' fait la différence, où la réponse acceptée et celles avec beaucoup de votes ne fonctionnent pas. +1

6voto

Nico Points 436

Il m'est arrivé la même chose. Il s'avère que

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

vous donne un objet non réinscriptible. Je l'ai résolu en utilisant :

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

Et à partir de ce moment-là, data était un objet JS standard, inscriptible.

0 votes

Comment y écrire ensuite ?

0 votes

Désolé Thom, je ne sais pas ce que tu veux dire... Après avoir fait $.extend... vous pouvez utiliser data comme vous le souhaitez : data.name = 'Nico'; data.questionSolved = true; y console.log(data) affichera ces propriétés nouvellement ajoutées

3voto

Super Cat Points 1303

Pour citer une citation :

Les attributs data- sont utilisés la première fois que la propriété data est accédée, puis ne sont plus accédés ou mutés (toutes les valeurs de données sont ensuite stockées en interne dans jQuery).

.data() - Documentiation jQuery

Notez que ce (franchement étrange ) la limitation est seulement retenue à l'utilisation de .data() .

La solution ? Utiliser .attr à la place.

Bien sûr, plusieurs d'entre vous peuvent se sentir mal à l'aise de ne pas utiliser la méthode qui lui est dédiée. Considérez le scénario suivant :

  • La "norme" est mise à jour de manière à ce que la partie "données" des attributs personnalisés ne soit plus nécessaire ou soit remplacée.

Bon sens - Pourquoi changeraient-ils un déjà établi attribut comme ça ? Imaginez simplement class commencent à être renommés en groupe y id a identifiant . L'Internet se briserait.

Et même dans ce cas, Javascript lui-même a la capacité de résoudre ce problème - Et bien sûr, malgré sa fameuse incompatibilité avec HTML, REGEX (et une variété de méthodes similaires) pourrait rapidement renommer vos attributs à cette nouvelle "norme" mythique.

TL;DR

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X