Skip to content

Select value is not updated correctly when input handler triggers class change #6690

@Frizi

Description

@Frizi

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

Activity

LinusBorg

LinusBorg commented on Sep 26, 2017

@LinusBorg
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

posva commented on Sep 26, 2017

@posva
Member

@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

chriscasola commented on Oct 3, 2017

@chriscasola
Contributor

@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)
})
added a commit that references this issue on Oct 5, 2017
bbd13af
yyx990803

yyx990803 commented on Oct 5, 2017

@yyx990803
Member

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

added a commit that references this issue on Oct 5, 2017
added a commit that references this issue on Feb 14, 2018
added a commit that references this issue on Jan 25, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      Participants

      @yyx990803@posva@Frizi@LinusBorg@chriscasola

      Issue actions

        Select value is not updated correctly when input handler triggers class change · Issue #6690 · vuejs/vue