Bug Tracker

Opened 7 years ago

Closed 7 years ago

Last modified 7 years ago

#11558 closed bug (invalid)

Invoking $.data("name", undefined) does not remove data as documented

Reported by: dcitron Owned by: Rick Waldron
Priority: high Milestone: 1.next
Component: data Version: 1.7.2
Keywords: Cc:
Blocked by: Blocking:

Description

The documentation for removeData says:

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().

However, "$data("name", undefined)" does not actually remove the stored data as documented.

In 1.7.1, passing undefined as the second argument would break the chain, which was fixed via #5571.

In 1.7.2 and edge, the chain is no longer broken, but the data is still not removed: http://jsfiddle.net/AvqeW/2/

Change History (12)

comment:1 Changed 7 years ago by Rick Waldron

Component: unfileddata
Milestone: None1.next
Owner: set to Rick Waldron
Priority: undecidedhigh
Status: newassigned

Confirmed. Patch or otherwise to follow

comment:2 Changed 7 years ago by gibson042

So there is a case where a setter should actually do something with undefined.

@rwaldron, this was in the back of my mind for the jQuery.access rewrite. Unless you've already gone down another path, I recommending adding another parameter forceSet either before or after pass, to be used disjunctively alongside value !== undefined. With that in place, the call to it in .data would need only minor tweaking:

  • fn: trigger getter behavior on arguments.length === 0 instead of value === undefined
  • forceSet: arguments.length > 1

comment:3 Changed 7 years ago by dmethvin

Do we really need to generalize this case, or can it just be handled in jQuery.data() as a special case?

comment:4 Changed 7 years ago by gibson042

We essentially are special-casing .data, but looking at that block of setter code makes me suspect that generalization is the most efficient way to do it:

parts[1] = value;
this.each(function() {
        var self = jQuery( this );

        self.triggerHandler( "setData" + part, parts );
        jQuery.data( this, key, value );
        self.triggerHandler( "changeData" + part, parts );
});

comment:5 Changed 7 years ago by Rick Waldron

Keywords: needsdocs added
Resolution: invalid
Status: assignedclosed

This is actually not a bug, the docs need to be updated to show that only "null" should be used.

Take a look at historic versions of jQuery supporting the behaviour:

needsdocs, update to:

To avoid a re-query of the data- attribute, set the name to a value of null (e.g. .data("name", null)) rather than using .removeData().

comment:6 Changed 7 years ago by dcitron

To be clear, this documentation-only change means that the only way to remove the data item (i.e. to make it so that a future invocation of .data("name") returns undefined) is to use .removeData("name") and suffer the possible re-query of the data- attribute.

comment:7 Changed 7 years ago by Rick Waldron

No, use "null"

comment:8 Changed 7 years ago by dcitron

But using "null" doesn't remove it ... that just sets it to "null", so comparison against undefined will not work, resulting in an arguably asymmetrical situation (a given data item is undefined when the page first loads but may be null later and mean the same thing).

It's fine--just a point worth making, I though.

comment:9 Changed 7 years ago by Rick Waldron

Please understand that "undefined" never worked the way you're expecting it to, in fact, jQuery actually has tests that confirm "undefined" never unsets a data property. The properties have actually never been "removed"

comment:10 Changed 7 years ago by dcitron

Right--that's fine. What's confusing is if the documentation implies that .data("name", null) will have the same effect as .removeData("name"). It will not:

  • .data("name", null) will set the value to null
    (future calls to .data("name") will yield null)
  • .removeData("name") will remove the data item entirely
    (future calls to .data("name") will yield undefined)

comment:11 Changed 7 years ago by Rick Waldron

Ok, thanks for the added clarification - that will be helpful when the docs are updated

comment:12 Changed 7 years ago by mikesherov

Keywords: needsdocs removed
Note: See TracTickets for help on using tickets.