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 value is not updated correctly when input handler triggers class change #6690

Closed
Frizi opened this issue Sep 25, 2017 · 4 comments
Closed

Comments

@Frizi
Copy link

Frizi commented Sep 25, 2017

Version

2.4.4
Current chrome, safari

Reproduction link

https://jsfiddle.net/6dupwfpf/6/

Steps to reproduce

  • open provided JSFiddle
  • change select box value to "Alpha"

What is expected?

Value should be changed and "green" class applied.

What is actually happening?

"green" class is applied, but value stays unchanged.


Provided fiddle runs on version 2.4.0, but I tested it locally on 2.4.4 and it behaves exactly the same.

This report is linked to vuelidate/vuelidate#192

@LinusBorg
Copy link
Member

I printed $data into the document to see what changed

https://jsfiddle.net/Linusborg/6dupwfpf/7/

  • test1 is correctly changed by v-model to 'alpha'
  • inputEvaluated correctly switches to true
  • green class is correctly applied

... what am I missing?

@posva
Copy link
Member

posva commented Sep 26, 2017

@LinusBorg The data changes but not the DOM (if we print it in a pre tag): https://jsfiddle.net/vkrjspxy/
However, using a change event instead makes it work: https://jsfiddle.net/tec1gqv3/1

@chriscasola
Copy link
Contributor

chriscasola commented Oct 3, 2017

@LinusBorg @posva

I took a look at what's happening here.

Simpler fiddle: https://jsfiddle.net/ert66j1x/1/

I think the flow of events leading to the bug is:

  1. User changes selection
  2. input event fires (because of v-on:input)
  3. The componentUpdated function is called because the input handler updates the value of data.inputEvaluated, which reverts the selection back to the original value of the v-model binding, since vue hasn't received the change event yet
  4. The change event fires and we loop over the select options which have been reset in step 3, so we don't update the vue instance to the correct value

As far as a solution, I think we want to make sure that the v-model change event is handled before any other user added event handlers. I was thinking we could do this in normalizeEvents but I think it's only possible to reorder handlers for the same event there.

I can create a pull request but a little guidance would be helpful.

NOTE: this is not replicable in firefox unless you put breakpoints in actuallySetSelected and in the listener callback that Vue adds for input element events.

Unit test for this issue:

it('should work on an element with an input binding', done => {
  const vm = new Vue({
    data: {
      test1: '',
      inputEvaluated: ''
    },
    template:
      `<select v-model="test1" v-on:input="inputEvaluated = 'blarg'" v-bind:name="inputEvaluated">` +
        '<option value="">test1 Please Select</option>' +
        '<option value="alpha">Alpha</option>' +
        '<option value="beta">Beta</option>' +
      '</select>'
  }).$mount()
  document.body.appendChild(vm.$el)

  vm.$el.children[1].selected = true

  triggerEvent(vm.$el, 'input')

  waitForUpdate(() => {
    triggerEvent(vm.$el, 'change')
  }).then(() => {
    expect(vm.$el.value).toBe('alpha')
  }).then(done)
})

chriscasola added a commit to chriscasola/vue that referenced this issue Oct 5, 2017
Use the "input" event instead of "change" when listening for
changes to the selection state since the "input" event will
always fire before the "change" event.

This avoids an issue where a user binds to the "input" event
with "v-bind" and causes the component to update and set its
model value back to the value of the select before it has
received the new selection value.

Fixes vuejs#6690
@yyx990803
Copy link
Member

yyx990803 commented Oct 5, 2017

FYI IE and Edge do not trigger input on <select> elements, so you should probably use change instead anyway...

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

Successfully merging a pull request may close this issue.

5 participants