0

Using jQuery 1.7.2, how do I update the data-* attrs in my elements when the data model is updated?

For example:

$('el').attr('data-x', 400);
var data = $('el').data( );
data.x += 100;

Changing the $(el).data() does not seem to push the changes back to the elements' data-* attrs.

Why would I want this? I would like to use the built in jQuery selectors with up-to-date data .

jedierikb
  • 12,752
  • 22
  • 95
  • 166

3 Answers3

4

You can do it like this:

$('el').attr('data-x', 400);
Zendy
  • 1,664
  • 1
  • 17
  • 24
  • Ok, yes. How do I push changes made to the data object back to the attr? ( I will update the question ) – jedierikb Aug 18 '12 at 04:04
  • oh..then just do $('el').attr('data-x', data.x); . The second parameter can be variable so you can change it however you feel like. – Zendy Aug 18 '12 at 04:12
  • depending on the complexity of data.x, I would probably want to JSON encode it 1st. http://stackoverflow.com/questions/191881/serializing-to-json-in-jquery – jedierikb Aug 18 '12 at 04:14
  • have you defined that `data-*` in your element? – Zendy Aug 18 '12 at 04:19
  • e.g. $('el').attr('data-x', '[1,2,3]'); $('el').data.x.push(4); $('el').attr('data-x', JSON.stringify($('el').data.x, null, 2)); – jedierikb Aug 18 '12 at 04:23
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/15491/discussion-between-zen-and-jedierikb) – Zendy Aug 18 '12 at 04:29
2

There's no reason to push data back onto the element's attribute unless you're going to be working directly with the attribute values (such as in a non-jQuery plugin). The changes only happen client-side, so it's much more performant to simply cache the values retrieved from the [data-*] attributes.

If you absolutely must update the attribute value, you should use the .attr() method.

Additionally, when retrieving data, it's important to know that the .data() method will try to figure out what sort of data type your content is:

<div data-foo="bar" data-baz="0" data-fizz='{"a":"b"}' data-bool="true"></div>

$('div').data('foo');       //returns "bar"
$('div').attr('data-foo');  //returns "bar"

$('div').data('baz');       //returns 0
$('div').attr('data-baz');  //returns "0"

$('div').data('fizz');      //returns {"a":"b"} as an object
$('div').attr('data-fizz'); //returns "{\"a\":\"b\"}"

$('div').data('bool');      //returns true
$('div').attr('data-bool'); //returns "true"
zzzzBov
  • 174,988
  • 54
  • 320
  • 367
  • I want to push the object back to attr as a string so that I can use selectors (since there are no data-selectors) – jedierikb Aug 18 '12 at 04:11
  • @jedierikb, you should make a custom selector using `$.expr[':']` or simply use the [`.filter()`](http://api.jquery.com/filter) method. There's no reason to push changes to an element's data back to its attributes. – zzzzBov Aug 18 '12 at 04:12
1

To work with data-* attributes, use the attr(name,value) method -- same as any other attribute value:

To set it:

$('#myDiv').attr('data-name', 'bob');

To get it:

var name = $('#myDiv').attr('data-name');

The difference between data-* attributes, and the $(..).data() function, is that the attributes can contain only string values, while jQuery's data() function allows you to attach (and later retrieve) actual javascript objects.

var obj = { 
  name: bob, age: 27,
  foo: function() { ... }
};
$('#myDiv').data('some.identifier', obj);

// then later
var obj2 = $('#myDiv').data('some.identifier');

console.log(obj2 === obj);  // true!
Lee
  • 13,462
  • 1
  • 32
  • 45