Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<select> bound with array performs incorrectly after splice() #3821

Closed
peteranny opened this issue Sep 30, 2016 · 6 comments
Closed

<select> bound with array performs incorrectly after splice() #3821

peteranny opened this issue Sep 30, 2016 · 6 comments
Labels

Comments

@peteranny
Copy link

Consider the following code:

<div id="demo">
  <select v-model="selected" number>
    <option v-for="opt in options" :value="$index" number>{{opt}}</option>
  </select>
</div>

In <select>, each option value is bound with $index. If we perform splice() on options, like, options.splice(0,1), $index does not correctly sync with options.

For example, let options=['a','b'] and the rendered HTML looks like (but not really):

<div id="demo">
  <select selectedIndex="0">
    <option value="0">a</option>
    <option value="1">b</option>
  </select>
</div>

After options.splice(0,1), then options=['b'], but the rendered HTML becomes:

<div id="demo">
  <select selectedIndex="0">
    <option value="1">b</option>
  </select>
</div>

The value of 'b' option does not become 1, which should be 0 because of $index. This may not be a bug, but this is kind of odd.

Below is the live demo of this issue:
https://jsfiddle.net/peteranny/trwp98g9/4/

@defcc
Copy link
Member

defcc commented Oct 1, 2016

Just add a selected attribute in your template selected="{{$index == selected}}"

I update the demo here https://jsfiddle.net/trwp98g9/5/

@fnlctrl
Copy link
Member

fnlctrl commented Oct 1, 2016

@peteranny Can you clarify what was the expected behavior?

After options.splice(0,1), then options=['b'], but the rendered HTML becomes:
<option value="1">b</option>

I'm not getting the same result as you provided from here:
Before clicking remove:
before

After clicking:
after

The value of 'b' option does not become 1, which should be 0 because of $index

So what exactly should it become? The value of 'b' was 1 before click, and became 0 after click.

@peteranny
Copy link
Author

peteranny commented Oct 2, 2016

@fnlctrl Um, thank you for your testing. I think I've asked the wrong question.
According to your testing, the value of 'b' did become 0 after click.

My true question is: now that the value of 'b' was 0, why was <select> not selecting 'b' anyway?
As seen in your image, <select> did not select any option at all, while <select> is ought to select the option with the value 0.
(And that is why I misguessed that the value of 'b' didn't change.)

@peteranny peteranny changed the title $index in option v-for value performs incorrectly after splice() <select> bound with array performs incorrectly after splice() Oct 2, 2016
@fnlctrl
Copy link
Member

fnlctrl commented Oct 2, 2016

@peteranny It may be a bug because selected remained 0 while the options changed, and the dom is supposed to reflect this change, but I'm not sure..

For now, you can try adding selected prop as @defcc suggested, (note that mustache binding for props/attrs is deprecated in 2.0, so please use :selected="$index == selected" instead)
Or you can add a track-by prop to <options>, which probably made vue think it's safe to update the selected value in dom. https://jsfiddle.net/74ncq90w/

@fnlctrl
Copy link
Member

fnlctrl commented Oct 2, 2016

Tested on 2.0 and it worked as expected: https://jsfiddle.net/dycmgzcm/
So I'm marking this as a bug of 1.x

@yyx990803
Copy link
Member

Closing 1.x issues as 1.x is now end of life and will only receive critical security patches.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants