10

Possible Duplicate:
jQuery .data() Not Updating DOM

I am having a problem with using the on attribute. I have written a small set of methods to send api calls.

The markup is like this:

<div data-global-id="1318" data-action="unfollow" class="action text-as-link follow-btn btn" style="text-decoration: none;">unfollow</div>

and have an event capture like this:

$(document).on('click','.action', function(){
  var t={};
  t.args={};
  t.args.global_id=$(this).data('global-id');
  t.global_id=t.args.global_id;
  t.action=$(this).data('action');
  t.identifier=t.action + '_v2';
  alert('here is action: ' + t.action);
  api_post_v1(t);
});

The api_post_v1 correctly sends the call.

There is some code to handle the callback and it sets the markup to:

<div data-global-id="1318" data-action="follow" class="action text-as-link follow-btn btn" style="text-decoration: none;">follow</div>

The code for this is like:

$foo=$('.action[data-action=unfollow][data-global-id='+global_id+']');
$foo.attr('data-action','follow');

The key piece is the data-action. I'd like the call to the event handler above to say it is 'follow' but it says it is still 'unfollow'.

The sequence is the following:

  1. load page, the data-action='unfollow'
  2. click this, api call gets made and you are not following this user; the callback sets data-action='follow'
  3. click this value again and the data-action is echoed as 'unfollow' rather than 'follow'

How could I tell jQuery to refresh the bindings of this event? I thought this was what $(document).on does.

thx

Community
  • 1
  • 1
timpone
  • 19,235
  • 36
  • 121
  • 211

1 Answers1

28

The data-* attributes & jQuery's .data() method are not interchangeable. Use this to get it:

t.action = $(this).attr('data-action');

You seem to be mixing jQuery's data method with HTML5's data-* attributes. These are two different things. The only time they interact with one another is when you first call .data on an element.

When you make a call to .data, jQuery looks for any data-* attributes, and adds it to the data collection. However, this only happens once. Subsequent calls to .data will not look at the element's data-* attributes.

To quote the jQuery docs:

The data- attributes are pulled in the first time the data property is accessed and then are no longer accessed or mutated (all data values are then stored internally in jQuery).


Since you're using .attr('data-action', 'follow') to set it, you should use .attr('data-action') to get it.

Note: $('.action[data-action=unfollow]') will not select an element that had the action set via jQuery's .data. Again, the two are not interchangeable.

Joseph Silber
  • 214,931
  • 59
  • 362
  • 292
  • thx, so got that first piece working. So, I'm a little confused - is it possible for me to select the data value the second time as I want to (ie the point you raise in the last paragraph)? like filter('data','unfollow') – timpone Sep 04 '12 at 21:24
  • @timpone - While you could use a filter, it's easier (and more efficient) to use an attribute selector. So, instead of using jQuery's `.data()` method, use `.attr('data-action')` exclusively. I've updated my answer. – Joseph Silber Sep 04 '12 at 21:27
  • cool, looks like this is working - but is what I'm doing really stupid (or cofusing) - should I change data-action to something like app-action and use attr to handle it? I know a lot of devs would frown on how I'm pushing things into the DOM this way – timpone Sep 04 '12 at 21:31
  • @timpone - I don't think what you're doing is stupid. Your code is clean, and works as expected. What more could you want ;) – Joseph Silber Sep 04 '12 at 21:32
  • thx, you clearly have (much) more experience - appreciate your advice. – timpone Sep 04 '12 at 21:34
  • what about this http://api.jquery.com/data/#data-html5 ? –  Sep 07 '12 at 15:49
  • @DanielRuf - Thanks for the reference. I added it to my answer. – Joseph Silber Sep 07 '12 at 15:52