Teja D
Teja D

Reputation: 143

Input cursor jumps to end of input field on input event

I’m trying to convert the user input to uppercase on input event

so, whenever I type a key in the input field I’m facing the following issues

  1. The cursor jumps to end of the input value when user types in the middle.
  2. the last typed character (not the last character) is not converting to uppercase.

Here is the link to JS fiddle https://jsfiddle.net/aeL051od/ to reproduce the issue

new Vue({
  el: "#app",
  data() {
    return {
      input: null
    }
  },
  methods: {
    handleInput(e) {
      this.input = e.target.value ?
        e.target.value.toString().toUpperCase() :
        e.target.value;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <input type="text" v-model="input" @input="handleInput"> {{ input }}
  <!-- {{ input }} is just for reference -->
</div>

Upvotes: 10

Views: 12324

Answers (3)

dagalti
dagalti

Reputation: 1956

{{ event ? event.target.value : null }} here you display target value.

you have to display converted input value. The should be like below

 <div id="app">
      <input type="text" v-model="input" @input="handleInput">
      <p>{{ input }}</p>
    </div>

for Cursor Jump issue get the position of the cursor on start then after update value set back cursor to start position

  handleInput(e) {
          var start = e.target.selectionStart;
            this.input = this.input.toUpperCase()
          this.$nextTick(()=>{
                  e.target.selectionStart = e.target.selectionEnd = start;
                    })
        }

Fiddle : https://jsfiddle.net/r53ecug6/

Upvotes: 1

anurupr
anurupr

Reputation: 2344

I was able to solve your issue but you need to introduce a new variable in the code

HTML:

<div id="app">
   <input type="text" v-model="input" @input="handleInput">
   <p>{{ updated_value }}</p>
</div>

JS:

new Vue({
   el: "#app",
   data() {
       return {
           input: null,
           updated_value: null
       }
   },
   methods: {
       handleInput(e) {
           this.input = e.target.value;
           this.updated_value = e.target.value ? e.target.value.toString().toUpperCase() 
         : e.target.value;
       }
   }
});

Link to fiddle

Summary:
1) Use a new variable (updated_value) to store the uppercase version of the input and use that as the value for <p>
2) This ensures that the input value is not updated , thus not causing the issue of the cursor to jump

Upvotes: 0

Roy J
Roy J

Reputation: 43881

If you (or Vue) copy a new value into an input, the cursor will be set to the end of the input. If you want to retain the previous position, you will need to capture the position, make the change, then on the $nextTick restore the position.

Also note that if you are going to set this.input in the handler, there's no point in your using v-model, too. It's also unlikely that saving the event is sensible, but you can.

new Vue({
  el: "#app",
  data() {
    return {
      input: null,
      event: null
    }
  },
  methods: {
    handleInput(e) {
      const el = e.target;
      const sel = el.selectionStart;
      const upperValue = el.value.toUpperCase();

      el.value = this.input = upperValue;
      this.event = e;
      this.$nextTick(() => {
        el.setSelectionRange(sel, sel);
      });
    }
  }
});
#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

input {
  margin-bottom: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <input type="text" @input="handleInput">
  <p>{{ event ? event.target.value : null }}</p>
  <p>
    {{input}}
  </p>
</div>

Upvotes: 6

Related Questions