Insert character at Cursor position in VUE JS

后端 未结 3 1496
小蘑菇
小蘑菇 2021-02-03 10:42

I have been trying to insert emoji in textarea exactly where the cursor is at. I looked around how tos in the web could not find anything specific in VUE JS. Most o

相关标签:
3条回答
  • 2021-02-03 11:06
    <!-- tag -->
    <textarea ref="yourTextarea" v-model.trim="txtContent" ......></textarea>
    

    // methods:
    insertSomething: function(insert) {
      const self = this;
      var tArea = this.$refs.yourTextarea;
      // filter:
      if (0 == insert) {
        return;
      }
      if (0 == cursorPos) {
        return;
      }
    
      // get cursor's position:
      var startPos = tArea.selectionStart,
        endPos = tArea.selectionEnd,
        cursorPos = startPos,
        tmpStr = tArea.value;
    
      // insert:
      self.txtContent = tmpStr.substring(0, startPos) + insert + tmpStr.substring(endPos, tmpStr.length);
    
      // move cursor:
      setTimeout(() => {
        cursorPos += insert.length;
        tArea.selectionStart = tArea.selectionEnd = cursorPos;
      }, 10);
    }

    0 讨论(0)
  • 2021-02-03 11:07

    I learned about setSelectionRange from a different question, and I used it to handle credit card number input. I will show my solution here so a person can perhaps become inspired by it.

    template:

    <input
        ref="input"
        v-model="value"
        @input="handleChange"
    >
    

    instance methods:

    data() {
        return {
            lastValue: '',
        }
    },
    
    methods: {
        setCursorPosition(el, pos) {
            el.focus();
            el.setSelectionRange(pos, pos);
        },
        handleChange() {
            // handle backspace event
            if (this.value.length < this.lastValue.length) {
                this.lastValue = this.value;
                this.$emit('input-changed', this.value);
                return;
            }
            // handle value-edit event
            if (this.$refs.input.selectionStart < this.value.length) {
                const startPos = this.$refs.input.selectionStart;
                this.value = this.value.replace(/\W/gi, '').replace(/(.{4})/g, '$1 ').trim();
                this.$nextTick(() => this.setCursorPosition(this.$refs.input, startPos));
                this.lastValue = this.value;
                this.$emit('input-changed', this.value);
                return;
            }
            // handle everything else
            this.value = this.value.replace(/\W/gi, '').replace(/(.{4})/g, '$1 ').trim();
            this.lastValue = this.value;
            this.$emit('input-changed', this.value);
        },
    },
    

    The goal with the above code is to add spaces into a credit card input, so 1234123412341234 is automatically reformatted to 1234 1234 1234 1234. A person venturing into this territory will notice that problems arise when editing the input value.

    You can see there are three conditions in my sample above. The last one is the default which simply reformats the current value with a 2-step combo: remove all spaces then adds a space every 4th character.

    If you comment out the two if blocks, you can watch the problems emerge.

    The first if block handles the backspace event. As you can see, every time the input changes, the value is captured as this.lastValue. When you press backspace, the goal of the first condition is to NOT run the regex. In my opinion, this is better UX. If you comment out that condition, you can see.

    The second if block handles the editing events. A good way to test it, is to enter a valid CC but omit the 3rd character, so that everything is off by one. Then add the character in. Everything should be good. Likewise if you backspace multiple characters out. The goal of the second condition is to properly manage the cursor position (or caret position if you prefer that nomenclature).

    You can safely delete the first condition and all references to lastValue and the code will still work. This is arguably simpler but worse UX.

    0 讨论(0)
  • 2021-02-03 11:17

    Two steps:

    1 get textarea element using a vue-way:

    1.1 Add ref attrbute to textarea tag in your template code:

    <textarea ref="ta"></textarea>
    

    1.2 get this element after mounted hook of this component:

    let textarea = this.$refs.ta
    

    2 get cursor position of textarea element.

    let cursorPosition = textarea.selectionStart
    

    Here is reference: ref

    0 讨论(0)
提交回复
热议问题