From 0c1cd6001efee397fa3acb1046a9d455493547bc Mon Sep 17 00:00:00 2001 From: Neco86 <33189641+Neco86@users.noreply.github.com> Date: Fri, 21 Apr 2023 14:41:07 +0800 Subject: [PATCH] Input: fix the issue of incorrect cursor position when updating the value asynchronously. When updating the value asynchronously, the cursor position is incorrect. --- packages/input/src/input.vue | 4 +++ packages/input/src/inputSelection.js | 38 ++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 packages/input/src/inputSelection.js diff --git a/packages/input/src/input.vue b/packages/input/src/input.vue index 26321f1cf..bb63bc0ee 100644 --- a/packages/input/src/input.vue +++ b/packages/input/src/input.vue @@ -113,6 +113,7 @@ import calcTextareaHeight from './calcTextareaHeight'; import merge from 'element-ui/src/utils/merge'; import {isKorean} from 'element-ui/src/utils/shared'; + import {getSelectionInformation, restoreSelection} from './inputSelection'; export default { name: 'ElInput', @@ -332,6 +333,7 @@ if (!input) return; if (input.value === this.nativeInputValue) return; input.value = this.nativeInputValue; + restoreSelection(this.selectionInformation); }, handleFocus(event) { this.focused = true; @@ -368,6 +370,8 @@ // ensure native input value is controlled // see: https://github.com/ElemeFE/element/issues/12850 this.$nextTick(this.setNativeInputValue); + + this.selectionInformation = getSelectionInformation(event.target); }, handleChange(event) { this.$emit('change', event.target.value); diff --git a/packages/input/src/inputSelection.js b/packages/input/src/inputSelection.js new file mode 100644 index 000000000..2f25cb8fb --- /dev/null +++ b/packages/input/src/inputSelection.js @@ -0,0 +1,38 @@ +export function getSelection(input) { + if ('selectionStart' in input) { + return { + start: input.selectionStart, + end: input.selectionEnd + }; + } + + return null; +} + +export function setSelection(input, offsets) { + const start = offsets.start; + let end = offsets.end; + if (end === undefined) { + end = start; + } + + if ('selectionStart' in input) { + input.selectionStart = start; + input.selectionEnd = Math.min(end, input.value.length); + } +} + +export function getSelectionInformation(input) { + return { + ele: input, + selectionRange: getSelection(input) + }; +} + +export function restoreSelection(selectionInformation) { + const {ele, selectionRange} = selectionInformation || {}; + if (selectionRange) { + setSelection(ele, selectionRange); + } +} +