fix(Field): incorrect cursor position when value length exceeds maxlength or when formatter is used (#11360)

This commit is contained in:
wnx 2022-12-18 10:29:30 +08:00 committed by GitHub
parent 7abb6bd6f9
commit 5a1188c468
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -282,6 +282,15 @@ export default defineComponent({
if (modelValue && getStringLength(modelValue) === +maxlength) {
return modelValue;
}
// Remove redundant interpolated values,
// make it consistent with the native input maxlength behavior.
const selectionEnd = inputRef.value?.selectionEnd;
if (state.focused && selectionEnd) {
const valueArr = [...value];
const exceededLength = valueArr.length - +maxlength;
valueArr.splice(selectionEnd - exceededLength, exceededLength);
return valueArr.join('');
}
return cutString(value, +maxlength);
}
return value;
@ -293,28 +302,58 @@ export default defineComponent({
) => {
const originalValue = value;
value = limitValueLength(value);
const isExceedLimit = value !== originalValue;
// When the value length exceeds maxlength,
// record the excess length for correcting the cursor position.
// https://github.com/youzan/vant/issues/11289
const limitDiffLen =
getStringLength(originalValue) - getStringLength(value);
if (props.type === 'number' || props.type === 'digit') {
const isNumber = props.type === 'number';
value = formatNumber(value, isNumber, isNumber);
}
let formatterDiffLen = 0;
if (props.formatter && trigger === props.formatTrigger) {
value = props.formatter(value);
const { formatter, maxlength } = props;
value = formatter(value);
// The length of the formatted value may exceed maxlength.
if (isDef(maxlength) && getStringLength(value) > maxlength) {
value = cutString(value, +maxlength);
}
if (inputRef.value && state.focused) {
const { selectionEnd } = inputRef.value;
// The value before the cursor of the original value.
const bcoVal = cutString(originalValue, selectionEnd!);
// Record the length change of `bcoVal` after formatting,
// which is used to correct the cursor position.
formatterDiffLen =
getStringLength(formatter(bcoVal)) - getStringLength(bcoVal);
}
}
if (inputRef.value && inputRef.value.value !== value) {
// When the value length exceeds maxlength and the input is focused,
// correct the cursor position to be consistent with the native behavior.
// https://github.com/youzan/vant/issues/11289
if (state.focused && isExceedLimit) {
const { selectionStart, selectionEnd } = inputRef.value;
// When the input is focused, correct the cursor position.
if (state.focused) {
let { selectionStart, selectionEnd } = inputRef.value;
inputRef.value.value = value;
inputRef.value.setSelectionRange(
selectionStart! - 1,
selectionEnd! - 1
);
if (isDef(selectionStart) && isDef(selectionEnd)) {
const valueLen = getStringLength(value);
if (limitDiffLen) {
selectionStart -= limitDiffLen;
selectionEnd -= limitDiffLen;
} else if (formatterDiffLen) {
selectionStart += formatterDiffLen;
selectionEnd += formatterDiffLen;
}
inputRef.value.setSelectionRange(
Math.min(selectionStart, valueLen),
Math.min(selectionEnd, valueLen)
);
}
} else {
inputRef.value.value = value;
}