3

I'm using jQuery, I have a simple list

<ul id="list">
 <li data-kind="foo">Foo1</li>
 <li data-kind="foo">Foo2</li>
 <li data-kind="foo">Foo3</li>
</ul>

in which I want to add this new element

<li data-kind="foo">Foo4</li>

I think this code should do the job

new_foo = jQuery('<li/>').data('kind', 'foo').text('Foo4');
new_foo.appendTo(jQuery('#list'));

but it works only half, it correctly adds the new <li> with 'Foo4' inside but it doesn't add the data-kind to the <li>

Checking in Chrome console I see that new_foo HAS data-kind="foo" but actually I can't see it in Chrome inspector and if I try in console to do

$('#list').find('li')

I see all items with data-kind EXCEPT the freshly added one.

Any idea why appendTo seems to ignore data fields?

Thank you!

EDIT1 Thanks to Gautam3164's suggestion I saw that using append() instead appendTo() it works. It seems that appendTo() doesn't preserve data attributes while append() does

EDIT2 Fixed error in my code example, there was a 'message' variable but it was 'new_foo' one

EDIT3 I need the presence of data-kind="foo" because I have a checkbox (with 'filter_switch' class) to show/hide items having data-kind="foo". When I was using .data() it didn't work with freshly created items, while using .attr() it works as expected.

Code is something like:

jQuery('.filter_switch').click(function(){
 elem = jQuery(this);
 if (elem.prop('checked')) {
  jQuery('li[data-kind="' + elem.data('kind') + '"]:hidden').show();
 } else {
  jQuery('li[data-kind="' + elem.data('kind') + '"]:visible').hide();
}

Thank you very much to everybody, this was my first question on stackoverflow and you were all amazing and very helpful! :)

SDp
  • 329
  • 3
  • 13
  • `message.appendTo(jQuery('#list'));` — what is `message`? Also I am not sure `data` produces any attributes, you may want `attr('data-kind', 'foo')`. – Andrey Shchekin May 09 '13 at 09:23
  • `.data()` stores data internally, it won't actually put the attribute on the element. If an element has `data-*` when loaded, these will be stored in the `data()` object. You could use `.attr()` if you actually want to 'see' the `data-*` but I don't think there's much point – billyonecan May 09 '13 at 09:26
  • Just looking at your edit as well, it has nothing to do with `append()` or `appendTo()`, it was the fact that, in his example, he was appending a string containing the `data-kind`, whereas in yours you were creating the element, and then (correctly) using `.data()` – billyonecan May 09 '13 at 09:31
  • @billyonecan you are right, using .attr('data-kind', 'foo') it works as I expected – SDp May 09 '13 at 09:32
  • @SDp why do you actually need to 'see' the `data-kind` in the actual markup though? It serves no purpose – billyonecan May 09 '13 at 09:34
  • Related http://stackoverflow.com/questions/6827810/unable-to-set-data-attribute-using-jquery-data-api/ – andyb May 09 '13 at 09:47
  • @billyonecan I added explanation (in EDIT3) why it was a problem, anyway with .attr() it works perfectly, thank you very much! – SDp May 09 '13 at 09:51

1 Answers1

2

The data is there its just not displayed in the markup displayed in the debugging tool. I assume jQuery stores this data as something other than an attribute.

var new_foo = jQuery('<li/>').data('kind', 'foo2').text('Foo4');
new_foo.appendTo($("#list"));

alert($("li:eq(3)").data("kind")); //alerts foo2

Working Example http://jsfiddle.net/JB549/

You will also notice that when you change data on an element the changes are not reflected in the markup.

//Notice that changes are not reflected
$("li:eq(0)").data("kind", "notFoo");
alert($("li:eq(0)").parent().html()); //markup doesn't contain notFoo

I'm just speculating but jQuery is managing this data internally. Which is most likely why you must prefix these attributes with data-. It provides jQuery the hook to grab the attribute and manage it.

Update Example http://jsfiddle.net/JB549/2/

This post provides some further insight.

Community
  • 1
  • 1
Kevin Bowersox
  • 93,289
  • 19
  • 159
  • 189
  • For DOM nodes jQuery has a global cache of data, and adds a new unique ID (not in the `id` attribute/property - I'm not sure what it's called) to the node that it uses to access the relevant entry in that cache. – Anthony Grist May 09 '13 at 09:34
  • @AnthonyGrist And none of that is related to the markup you see I assume? Does jQuery do some sort of quick scan upon load or selection to find the `data-*` attributes on elements? – Kevin Bowersox May 09 '13 at 09:38
  • @KevinBowersox My understanding is that any `data-*` present in markup are added to the corresponding elements `data` object, after which, they have no relation to eachother whatsoever – billyonecan May 09 '13 at 09:40
  • @KevinBowersox Yes, it does an initial scan (I'm not entirely sure when, selection would make sense though) to convert `data-*` attributes to entries in the data for that node. After that, as billyonecan said, the two are unrelated - modifying the value of the attribute using `.attr()` won't update what's retrieved by `.data()` and vice versa. – Anthony Grist May 09 '13 at 09:51