Bug Tracker

Opened 9 years ago

Closed 9 years ago

Last modified 8 years ago

#8813 closed bug (patchwelcome)

Using .val() on a select with non-existent value produces invalid result

Reported by: anonymous Owned by: timmywil
Priority: low Milestone: 1.6
Component: attributes Version: 1.5.2
Keywords: val Cc:
Blocked by: Blocking:

Description

If you start with:

<select id="test_select">
      <option value="1" selected="selected">One</option>
      <option value="2">Two</option>
</select>

And do:

$('#test_select').val("3")

jQuery removes the selected attribute from the first option, but then can't find a matching option to select. Depending on the browser, the final behavior is different. In the last version of Firefox 3, the first option is selected. In Safari 5.0.4, you get a blank select (no option selected). Either way, you're setting a value and the value isn't being set.

With a non-multiple select, jQuery needs to preserve the existing value if it can't set the requested one. I don't think there's any other safe behavior, since .val() can't return true/false for success.

Change History (12)

comment:1 Changed 9 years ago by timmywil

Component: unfiledattributes
Keywords: val added
Milestone: 1.next1.6
Owner: set to timmywil
Priority: undecidedhigh
Status: newassigned

comment:2 Changed 9 years ago by timmywil

Keywords: needsreview added

Actually, having reviewed the source, this looks intentional. http://bot-t.com/jquery.js#1991 I'll tag this as needsreview. My guess is we probably don't want this behavior as it's not consistent. After setting the selectedIndex to -1, val then returns null instead of the default selected option on retrieval (for certain browsers at least such as chrome 10). F4 returns the default selected option. Depending on which direction we want to go( whether to return null or the default 1), we should probably unify this across browsers.

comment:3 Changed 9 years ago by Rick Waldron

Priority: highlow
Resolution: invalid
Status: assignedclosed

This is not a jQuery bug, to add a new, previously non-existent value to a select menu, see the following: http://jsfiddle.net/rwaldron/NxQyh/

comment:4 in reply to:  3 Changed 9 years ago by timmywil

Replying to rwaldron:

This is not a jQuery bug, to add a new, previously non-existent value to a select menu, see the following: http://jsfiddle.net/rwaldron/NxQyh/

Not sure you understand what I meant. It's not about being able to select new options. It's about passing a value that isn't one of the options. We are the ones setting the selectedIndex to -1 instead of letting nothing happen, which is creating the inconsistency between browsers. I think this is valid.

comment:5 Changed 9 years ago by timmywil

Resolution: invalid
Status: closedreopened

Given that dynamic values are common in setting values of select elements, reopening for now. I'm not sure rwaldron understood the issue here.

comment:6 Changed 9 years ago by anonymous

I'm the reporter of this bug. Timmywil, your assessment of my intent is correct. I am not trying to add new options -- just the opposite. I'm trying to set a value without knowing if the value is available. Rather than check ahead of time, I want to check after calling .val():

var select = $('#select_id');
select.val(value);
if (select.val() != value)
    //No option matched, take appropriate action

If I can't do this, I have to check $('#select_id').find('option[value="' + value + '"]').length before every .val(), which is probably redundant. (I'm guessing jQuery uses that same find() in the val() call.)

comment:7 Changed 9 years ago by timmywil

I think you meant rwaldron. That's exactly what I said.

comment:8 in reply to:  7 Changed 9 years ago by anonymous

Replying to timmywil:

I think you meant rwaldron. That's exactly what I said.

Right. That's why I said you were correct! :-)

I appreciate everything the jQuery team does.

comment:9 Changed 9 years ago by Rick Waldron

When you attempt to set a select to a value that does not exist, jQuery behaves the same way that it would if no option was selected, which according to html spec, the correct behaviour is to set the selectedIndex to -1; how the browser handles this is spec dependent. Try this just testing the return from select.val( value ) ?

comment:10 Changed 9 years ago by timmywil

Keywords: needsreview removed
Resolution: patchwelcome
Status: reopenedclosed

Woops, I read "incorrect". Sorry OP.

Anyway, rwaldron and I have discussed this ticket and there do not seem to be other tickets related to this problem. And rwaldron brings up another good point. This is a browser bug. The current version of webkit does not react correctly to setting selectedIndex to -1, but the issue does not exist in Chromium 12. If there are more tickets about this issue in the future, we can investigate further and possibly provide a patch. Currently, the same code is being used for multiple and single select elements, which is ideal since it makes the code short. I could not think of a way to fix without calling val again or differentiating between single and multiple, which does not seem worth it. The user might as well validate the entry. If someone would like to present a patch that has no perf loss and does not inflate the setter for selects, I think we would welcome it.

comment:11 Changed 9 years ago by anonymous

Thanks for the explanation. I did suspect that this is a WebKit oddity.

In this situation I need the selects to always have a selection, which WebKit isn't doing. I also need the selected option's text to display elsewhere. Instead of checking for WebKit's behavior every time, I added a simple function. It only changes the selection if the new value exists, and returns the selected object's DOM object so I can access its value and text without additional jQuery calls.

$.fn.setSelectVal = function(value)
{
	this.children('option[value="' + value + '"]').attr('selected', 'selected');
	var select = this.get(0);
	return select.options[select.selectedIndex];
};

In both Safari and Firefox, adding the selected attribute to an option automatically causes attribute removal on the prior selected option. I'm not sure if it's smart to count on this, but it works for me right now and I have a very small user base.

comment:12 Changed 9 years ago by timmywil

#5394 is a duplicate of this ticket.

Note: See TracTickets for help on using tickets.