I want to have a text field (<input>
in HTML) that the user can only use to write text, but when deleting the text, it should prevent him from updating the state of the input element.
<input type="text" />
I couldn't come up with a solution except to detect the user key presses on the keyboard, i.e, using the onKeyUp
attribute, and watch the user keystrokes until he presses the Backspace character:
const input = document.querySelector('input')
input.addEventListener('keydown', (e) => {
const keyCode = e.keyCode
if (keyCode === 8) console.log("Backspace pressed!")
})
<input type="text" />
However, there's a missing part here, even though the user won't be able to clear the input content by the Backspace key, he can instead use the Del
key.
So I would have then to handle the Del key the same way I handle the Backspace key.
Now, there's another problem, which is trying to modify the input content by overwriting the content as follows:
and then, after that, I will have to prevent the user from editing the text by cutting
the content (which I have no idea how to do).
So, what are the alternatives?
Please feel free to use HTML, JavaScript, CSS.
If you're using React, I was able to solve this problem simply by checking if the length of the input value is shorter than the one being memorized in the state, then prevent the user from updating the state:
The answer resides between controlling the value prop (or attribute if you wish) and the onChange handler.
const [inputVal, setInputVal] = useState('')
const handleChange = (e) => {
const value = e.target.value
if(value.length < inputVal.length) return // prevent modifications
setInputVal(value)
}
return <input value={inputVal} onChange={handleChange}/>
Now, the question is, how to do the same when using only HTML/JavaScript?
CodePudding user response:
Perhaps something like this? Then it doesn't matter what they press.
const input = document.querySelector('input')
let previousState = input.value;
input.addEventListener('keydown', (e) => {
if ( previousState.length > input.value.length ) input.value = previousState;
previousState = input.value;
})
CodePudding user response:
In the keydown event, put whatever keycodes you want in an array and see if the current keycode is included. Then create a select event, and blur the input when it fires.
const input = document.querySelector('input');
input.addEventListener('keydown', (e) => {
if ([8, 46].includes(e.keyCode)) {
e.preventDefault()
}
})
input.addEventListener('select', (e) => {
e.target.blur()
})
<input type="text" />
CodePudding user response:
@dqhendricks answer is in the right way, but misses some possibilities:
- User can hit backspace (reduce length by one) (covered)
- User can select a piece of text and hit backspace or other key (covered)
- User can select a piece (or all text) and replace by a different string with same length. (Not covered)
So my suggestion is:
You should listen for change event, then compare the previous string, if the new string starts with the previous string, it's ok. Otherwise we revert the change.
In code ir should look like:
const input = document.querySelector('input');
let previousState = input.value; // initial state
input.addEventListener('change', (e) => {
if (!input.value.startsWith(previousState)) {
input.value = previousState; // revert change
}
previousState = input.value;
})
CodePudding user response:
you can check the length of the input's value, if it became shorter replace it with the previous value
let value;
input.addEventListener('change', ()=>{
if(value && input.value.length < value.length) input.value=value;
else value=input.value;
}
CodePudding user response:
You must have some piece of code that sets the value from the barcode scanner. Once that is being set, also do input.dataset.barcodeValue="scanresult"
.
Then to make it sufficiently difficult for a regular user you need to prevent several things:
- pasting
- cutting
- typing over the barcode value
- dragging text into the input
- pressing delete or backspace which would mess up the barcode value.
All of this is covered in the input
event.
const input = document.querySelector('#bc-value');
function setValueFromBarcodeScanner(val) {
input.value = input.dataset.barcodeValue = val;
input.addEventListener('input', (e) => {
const { barcodeValue } = input.dataset;codeValue)) input.value = barcodeValue;
})
if (barcodeValue && !input.value.startsWith(bar
}
<input type="text" id="bc-value" />
<button type="button" onclick="setValueFromBarcodeScanner('433-224-221-456')">Set value from Barcode Scanner</button>
CodePudding user response:
I think this might work for you:
var inputElement = document.getElementById('write-only-input');
var lastValue = '';
inputElement.oninput = function(e) {
if (inputElement.value.startsWith(lastValue)) {
lastValue = inputElement.value;
} else {
inputElement.value = lastValue;
}
}
<input type="text" id="write-only-input" />