Bug Tracker

Ticket #9166 (closed bug: duplicate)

Opened 4 years ago

Last modified 15 months ago

Prop not setting property if it had previously been removed, and Chrome inconsistency

Reported by: jamietre Owned by:
Priority: low Milestone: 1.next
Component: attributes Version: 1.6
Keywords: Cc:
Blocking: Blocked by:

Description

 http://jsfiddle.net/22ERz/8/

After this script runs the test field is not actually disabled (following setting "disabled" property to "true", then "false", then "true" again.) Yet the reported values in the log indicate that jQuery thinks the property is there. Inspecting the HTML shows that it does not exist in the DOM. This behavior is consistent across all browsers.

Additionally, the results returned by testing "prop" value are incorrect in Chrome.

Initially, Chrome correctly reports "false" for prop on a missing property. However, after adding then removing "disabled" Chrome reports "undefined" whereas IE and FF correctly report "false".

Change History

comment:1 Changed 4 years ago by rwaldron

  • Priority changed from undecided to low
  • Resolution set to duplicate
  • Status changed from new to closed
  • Component changed from unfiled to attributes

comment:2 Changed 4 years ago by rwaldron

Duplicate of #9140.

comment:3 Changed 4 years ago by timmywil

docs updated to make it clear that .removeProp() should not be used on native properties.

comment:4 Changed 4 years ago by jamietre

Shouldn't methods behave consistently across browsers even if doing things that one "shouldn't" do with them? I would think that if one shouldn't do this then jQuery should either not let you do it, or act as if you used 'prop("native",false)'.

comment:5 Changed 4 years ago by timmywil

.removeProp() was only added so that you can remove user-defined properties that were added with .prop(). However, you'll generally want to use .data() instead anyway. It is a simple, powerful, and dangerous function, but I think we just need clear documentation or we'll be playing the guessing game too much on what the user wants.

comment:6 Changed 4 years ago by jamietre

OK - I was only using it because behavior is inconsistent when using "attr" to set/unset "disabled" per your previous comment (basically was following the example from your original jsfiddle).

There are so many different ways one could try to do this:

attr("disabled",true); attr("disabled","disabled"); attr("disabled",false); attr("disabled,""); removeAttr("disabled"); prop("disabled",true); prop("disabled",false); removeProp("disabled)");

At this point it appears that the only "right" way to do it is

prop("disabled",true); prop("disabled",false):

This is a pretty confusing array of options with many wrong answers (but not just wrong answers - answer that *appear* to work because they do in some browsers) for a very simple need. Given that if you google "how I set something disabled with jQuery" you get every answer EXCEPT prop (which has only been around since 1.6.0), this is going to trip people up for a long time to come.

Maybe it's time for disable() and enable() to become native functions :)

comment:7 Changed 4 years ago by timmywil

Yea, we agree it's confusing. disable and enable might be good ideas for 1.7. However, we are reverting attr in 1.6.1 to work the way it used to for boolean attributes to reduce the confusion. You should still use prop for changing these values as that is what attr will be doing internally in 1.6.1.

I don't want to go changing removeProp when it was just introduced though. The documentation for it makes the dangers clear now.

Last edited 4 years ago by timmywil (previous) (diff)

comment:8 Changed 4 years ago by jamietre

Thanks for the discussion. I'll proceed with prop("disabled",true|false) and am glad to have a deeper understanding of the issue.

comment:9 Changed 15 months ago by anonymous

This bug still exist I'm using version 1.7.1 and the following code doesn't change the HTML DOM but only visually !

var checkboxes = $('input[type="checkbox"]');
var state = $(checkboxes).first().is(':checked');				
	checkboxes.each(function() {
		$(this).prop('checked', !state);		
	});	

I've fixed this code by adding this line just below .prop() call:

$(this).attr('checked', $(this).is(':checked'));

.attr() changes the DOM.

Note: See TracTickets for help on using tickets.