I need to handle basic users to handle most of edge cases.
I have an input which value is being parsed after typing.
Right now I have problems when a user moves the cursor at the beginning of the input and adds some characters.
What I thought to achieve is:
The code could look like this:
const myInput = document.querySelector("[my-input]");
const myInputMaxlen = 2;
myInput.addEventListener("input", () => {
const val = myInput.value;
const wasBefore = val.selectionStart < val.length;
if (val.length > myInputMaxlen) {
myInput.value = wasBefore
? myInput.value.slice(0, myInputMaxlen - 1)
: myInput.value.slice(1)
}
});
<input my-input type="text" maxlength="3" value="" />
The goal is assuming the maxLength of the input is 2, having the input character and one of the already existing characters
Ok, basically the code I wrote is already fine. I added some logic to handle the caret position after editing the string, to make the typing more straight forward.
Thanks to Mudasir for the tips.
Here's the final code for generic Javascript:
const myInput = document.querySelector("[my-input]");
const myInputMaxlen = 2;
myInput.addEventListener("input", () => {
const val = myInput.value;
const caretPos = myInput.selectionStart;
if (val.length > myInputMaxlen) {
if(caretPos < val.length) {
myInput.value = val.slice(0, 1) + val.slice(1, myInputMaxlen);
caretPos < 2 && setCaretPos(myInput, caretPos);
}
else {
myInput.value = val.slice(1, 1 + myInputMaxlen);
}
}
});
function setCaretPos(ctrl, pos) {
if (ctrl.setSelectionRange) {
ctrl.focus();
ctrl.setSelectionRange(pos, pos);
}
else if (ctrl.createTextRange) {
var range = ctrl.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
else {
console.warn("couldn't set caret position");
}
}
<input my-input type="text" value="" maxlength="3" />
And here's the actual Angular version I was working on:
onHourInput($event: Event): void {
const t = $event.target as HTMLInputElement;
if (this.hour.length > this.inputMaxlen) {
this.hour = t.selectionStart < this.hour.length
? this.hour.slice(0, 1) + this.hour.slice(1, this.inputMaxlen)
: this.hour.slice(1, 1 + this.inputMaxlen);
}
}