14

If i open https://v2.vuejs.org/v2/guide/forms.html#Text and edit text - no effect on typing text in mobile chrome. @keyup @input @keypress - v-model does not change when I'm typing

<input v-model="message" @keyup="log" placeholder="Edit">
<p>Edited: {{ message }}</p>

How can i fix it? I need get input value on typing (@keyup @input)

tony19
  • 125,647
  • 18
  • 229
  • 307
ebyratu
  • 311
  • 1
  • 3
  • 13

4 Answers4

26

Update: After a lot of discussion, I've come to understand that this is a feature, not a bug. v-model is more complicated than you might at first think, and a mobile 'keyboard' is more complicated than a keyboard. This behaviour can surprise, but it's not wrong. Code your @input separately if you want something else.


Houston we might have a problem. Vue does not seem to be doing what it says on the tin. V-model is supposed to update on input, but if we decompose the v-model and code the @input explicitly, it works fine on mobile. (both inputs behave normally in chrome desktop)

For display on mobiles, the issue can be seen at... https://jsbin.com/juzakis/1

See this github issue.

function doIt(){
    var vm = new Vue({
        el : '#vueRoot',
        data : {message : '',message1 : ''}
    })
}
doIt();
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<div id='vueRoot'>
<h1>v-model</h1>
  <div>
    <input type='text'
      v-model='message'
        >
    {{message}}
  </div>
  <h1>Decomposed</h1>
  <div>
    <input type='text'
        :value='message1'
        @input='evt=>message1=evt.target.value'
        >
    {{message1}}
  </div>
</div>
bbsimonbb
  • 27,056
  • 15
  • 80
  • 110
  • Thanks, this works fine for me. But is there an explanation for this? I only experienced this behavior on one of our testing devices. – Jan Heinzle Jan 09 '19 at 11:22
  • 4
    [I submitted this issue](https://github.com/vuejs/vue/issues/9299) on github, and it was closed soon after. Clearly not all devices are affected. Anyone finding themselves here might like to comment on the closed issue. In the office, the issue appeared on 5 out of 5 androids tested including galaxy S4 => S9. – bbsimonbb Jan 11 '19 at 14:41
  • After a lot of discussion, I've come to understand that this is a feature, not a bug. v-model is a little more complicated than it says on the tin. – bbsimonbb Feb 16 '20 at 11:00
  • What does "tin" mean? – Leonardo Sibela Sep 21 '20 at 00:30
  • ...the packaging, the guide, – bbsimonbb Sep 22 '20 at 09:53
5

I tried all solutions I could find on the internet, nothing worked for me. in the end i came up with this, finally works on android!

Trick is to use compositionupdate event:

 <input type="text" ... v-model="myinputbox" @compositionupdate="compositionUpdate($event)">
    
    ......
    ......

methods: {
    compositionUpdate: function(event)
    {
        this.myinputbox = event.data;
    },
}
rompish
  • 123
  • 2
  • 9
1

Ok, I dont know if there is another solution for this issue, but it can be solved with a simple directive:

Vue.directive('$model', {
    bind: function (el, binding, vnode) {
        el.oninput = () => (vnode.context[binding.expression] = el.value)
    }
})

using it just like

<input v-$model="{toBind}">

There is an issue on the oficial repo, and they say this is the normal behavior (because the composition mode), but I still need the functionality

Diego Meza
  • 197
  • 1
  • 10
0

EDIT: A simpler solution for me was to just use @input.native. Also, the this event has (now?) a isComposing attribute which we can use to either take $event.data into account, or $event.target.value

In my case, the only scheme that worked was handling @keydown to save the value before the user action, and handling @keyup to process the event if the value had changed. NOTE: the disadvantage of this is that any non-keyboard input (like copy/paste with a mouse) will not work.

<md-input
    v-else
    :value="myValue"
    ref="input"
    @keydown="keyDownValue = $event.target.value"
    @keyup="handleKeyUp($event)"
    @blur="handleBlur()"
/>

With handleKeyUp in my case being:

handleKeyUp(evt){
  if(evt.target.value !== this.keyDownValue){
    this.$emit('edited', evt);
  }
}

My use case was the following:

I requested a search endpoint in the backend to get suggestions as the user typed. Solutions like handling @compositionupdate lead to sending several several requests to the backend (I also needed @input for non-mobile devices). I reduced the number of requests sent by correctly handling @compositionStarted, but there was still cases where 2 requests were sent for just 1 character typed (when composition was left then, e.g. with space character, then re-entered, e.g. with backspace character).

Josuah Aron
  • 141
  • 1
  • 8