31

I think I'm using removeData correctly but it doesn't seem to be working, here's what I'm seeing in the dev console, could anyone explain what I'm doing wrong?

I'm outputting the current data attribute value, calling removeData, then outputting the value again and its still there.

$('.questionList > li').eq(1).data('fieldlength')
3
$('.questionList > li').eq(1).removeData('fieldlength');
[
<li class=​"questionBox" data-createproblem=​"false" data-fieldlength=​"3" data-picklistvalues data-required=​"true" data-sfid=​"a04d000000ZBaM3AAL" data-type=​"Text">​
<div class=​"questionLabel">​Birthdate​</div>​
</li>​
]
$('.questionList > li').eq(1).data('fieldlength')
3
turbo2oh
  • 2,849
  • 6
  • 34
  • 46

6 Answers6

53

There is bit of gotcha I wanted to clarify in case anyone else stumbles upon it...

If you have HTML5 data-* attributes on an element you need to use jQuery's removeAttr() instead of removeData() if you want to remove them from the element in the DOM.

For example, to actually remove a data attribute from an element you need to use:

$({selector}).removeAttr('data-fieldlength');

You can read values like this with $({selector}).data('fieldlength') but removeData() doesn't actually remove them if they are HTML attributes on an element present in the source of the page (it just deletes it in memory, so that if you query it again with jQuery it appears to have been removed).

Personally I think this behaviour is broken and I'm sure catches a lot of people out.

Yonggoo Noh
  • 1,811
  • 3
  • 22
  • 37
Iain Collins
  • 6,774
  • 3
  • 43
  • 43
  • I think that it would be better, from a coding perspective, to retain the `data-` attribute in the DOM, but set the JavaScript `.data()` variable to `null`. This gives the desired result in jQuery without destroying the DOM attribute unnecessarily; there's always a possibility it will be used elsewhere (for instance, CSS styles might depend on it). – Blazemonger Mar 20 '14 at 14:48
  • 1
    @Blazemonger, as a note, I've tried to change `data-remote` from true to false, and using `.data()` or `.removeData()` didn't worked, `.removeAttr()` worked fine. So for those who don't care about the DOM attribute this method works great. – rmagnum2002 Sep 01 '14 at 04:10
38

It's because your data originates in the HTML data-fieldlength attribute. According to the docs:

When using .removeData("name"), jQuery will attempt to locate a data- attribute on the element if no property by that name is in the internal data cache. To avoid a re-query of the data- attribute, set the name to a value of either null or undefined (e.g. .data("name", undefined)) rather than using .removeData().

So instead of

$('.questionList > li').eq(1).removeData('fieldlength');

you should do

$('.questionList > li').eq(1).data('fieldlength',null);
Blazemonger
  • 90,923
  • 26
  • 142
  • 180
  • Thanks! That works, though I'm still a little fuzzy on exactly what is going on even after reading the explanation in the docs. – turbo2oh May 17 '13 at 18:26
  • 2
    As I understand it: the `.data()` method checks for a JavaScript value for a value, and if it can't find one, it slurps in the `data-` attribute instead. You removed the internal JavaScript value, so it went to the `data-` attribute like it was designed to. If instead you set the JavaScript value to `null`, it retrieves that happily and ignores the `data-` attribute. – Blazemonger May 17 '13 at 18:30
  • 1
    I used to think that the `data-` attributes were slurped in just once, when the page was first loaded -- and if that were the case, your code would have worked fine. In fact, [the docs](http://api.jquery.com/removeData/) suggest that approach *was* used prior to jQuery 1.4.3 – Blazemonger May 17 '13 at 19:11
  • 2
    It seems, contrary to the quoted documentation above, passing `undefined` has no effect, but passing `null` to the `data()` call sets the value to nothing. – Jens Apr 22 '15 at 20:38
4

.removeData() will only remove data from jQuery's internal .data() cache so any corresponding data- attributes on the element will not be removed. A later call to data() will therefore re-retrieve the value from the element's data- attribute. To prevent this, use .removeAttr() alongside .removeData() to remove the data- attribute as well.

Example:

$('div').removeData('info');
$('div').removeAttr('data-info');

Then set either:

$('div').data('info', 222);
$('div').attr('data-info', 222);
ztrat4dkyle
  • 1,652
  • 2
  • 13
  • 13
3

Actually this works better for me. Because it leaves the attribute intact in the element but with no assigned value to it.

$(selector).attr("data-fieldlength","");
Gardoku
  • 31
  • 4
  • Spent a bunch of time on this. I think there is a bug in JQuery. I ended up using this variant as well \ $(thisTr).find(".tdTspec").attr("data-tspecno", "0");\ – pat capozzi Sep 03 '15 at 17:52
2

In Hidden Field using custom data attribute to store object data Should use .removeAttr() instead of .removeData() using ID

-1

One option is to use the DOM's own remove method. Index 0 references the first DOM element in the jQuery result set, so you can make direct DOM calls on it.

console.log($('[data-fieldlength]').data('fieldlength'));
$('[data-fieldlength]')[0].removeAttribute('data-fieldlength');
console.log($('[data-fieldlength]').data('fieldlength'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div data-fieldlength="42">Hello Elliot</div>
OXiGEN
  • 2,041
  • 25
  • 19