I am using the example code in this path https://redux-form.com/6.6.3/examples/fieldlevelvalidation/ to validate number input
const number = value => value && isNaN(Number(value)) ? 'Must be a number' : undefined
It won't stop me from typing non-numeric characters in the Microsoft Edge. How can I work around this?
The type="number" converts the input to a number input field. On mobile you would get the keyboard with only numbers on it. So it' more a browser thing. The validation will just prevent submitting and showing error messages when entering wrong values.
If you want to do this on your on use the onKeyPress event:
const NumberInput = ()=>{
const onKeyPress = (e) => {
if(e.which<48 || e.which>57) {
e.preventDefault()
}
}
return (
<input onKeyPress={onKeyPress} />
)
}
small example: https://codesandbox.io/s/loving-lichterman-7eel4
Related
The HTML5 checkValidity() / reportValidity() methods don't seem to work if values are set via JavaScript.
Consider this example (JSFiddle):
<input id="text-field" maxlength="3" placeholder="Max len: 3 chars" />
<button id="set-field-value">Set</button>
<button id="check-valid">Is valid?</button>
<script>
window.onload = function() {
var textField = document.getElementById('text-field');
document.getElementById('set-field-value').onclick = function() {
textField.value = 'This is a very looooooooooooooooooooooooooooooong text';
};
document.getElementById('check-valid').onclick = function() {
window.alert(textField.checkValidity());
};
};
</script>
If you click the Set button, the value of the input field is set to an invalid value (it's length is greater that 3 characters), but the checkValidity() method still says that the input is valid (checked on Chrome, Edge and Firefox).
Why? Is there a way to determine is the field is valid even if its value is set via code?
I investigated this a while. It seems that you're at least missing <form> wrapping the input + button content.
But still, even if I tried to set input field required, still the ValidityObject won't notice that length is exceeded.
As a semi-workaround, I came with an idea of using pattern property:
<input id='textfield' pattern='\S{0,3}'>
(= \S stands for 'all characters except spaces')
This at least will prevent for content beyond three characters. In addition, you can have a setCustomValidity message for invalid cases.
See working example at: https://codepen.io/zvona/pen/rNavqxP?editors=1010
I've tried a few things that led me to understand that checkValidity does not check the value itself.
When I click on #check-validity I get :
textField.validity.tooLong // false
textField.validity.valid // true
textField.value // This is a very looooooooooooooooooooooooooooooong text
When I type myself in the input, my browser does not let me type more than 3 characters.
Why?
Precisely I don't know, but there is this awesome article on constraint validation that is worth having a look.
Is there a way to determine is the field is valid even if its value is
set via code?
textField.value returns your string, you can then access it's length. In this context, I would have anyway prefered this way.
const tooLong = textField.value.length > 3;
if (tooLong) window.alert('Something');
I hope it helps.
You should check if the form valid not the input. BUT it seems that the maxLength attribute is not something that trigger validation at all...
If you want to check length of input text you can do that with this:
window.onload = function() {
var textField = document.getElementById('text-field');
document.getElementById('set-field-value').onclick = function() { textField.value = 'ab'; };
document.getElementById('check-valid').onclick = function() {
if (textField.value && // if exist AND
textField.value.length > 2 && // if value have 3 charecter at least
textField.value.trim().length > 2 // if value is not just spaces
) {alert ('input OK');} // alert that input ok
else { alert('please insert at least 3 charecters');} // else alert error
};
};
<form id="formCheck">
<input type="text" id="text-field" min="3" />
<button type="button" id="set-field-value">Set</button>
<button type="button" id="check-valid">Is valid?</button>
</form>
The checkValidity() method works as expected on this example (using input number and min attribute) though:
window.onload = function() {
var theForm = document.getElementById('formCheck');
var numberField = document.getElementById('number-field');
document.getElementById('set-field-value').onclick = function() { numberField.value = '2'; };
document.getElementById('check-valid').onclick = function() {
window.alert(theForm.checkValidity());
};
};
<form id="formCheck">
<input type="number" id="number-field" min="3" />
<button type="button" id="set-field-value">Set</button>
<button type="button" id="check-valid">Is valid?</button>
</form>
How can I check if the user types nothing in the search bar and if its a number return nothing. And also, how do I clear the user recent value? I've manage to clear the value, but after the conditional statement using the same input.value = '', i receive an error.
form.addEventListener('submit', e => {
e.preventDefault();
input.value = ''; // I'm assuming this get overwritten;
if(input.value === '') {
console.error('Please type anything in the search bar');
} else {
return recipes();
}
});
So from the code above, when the user types in nothing it will spit our error in the console, and if users were to type in both A-Z and 0-9 the recipes will still load.
I've left with when users type in numbers it will spit out error in console and lastly, to clear user input value after typing.
This is a practice for my beginner portfolio.
First you don't need to set input.value to null, it'll be setup to the default value into the HTML tag.
Also, this depend on how you define your input variable, if it's common like the following example, it's will work fine with input.value
let form = document.getElementsByTagName('form')[0]
let input = document.querySelector('[type=text]')
form.addEventListener('submit', e => {
e.preventDefault();
if(input.value === '') {
console.error('Please type anything in the search bar');
} else {
console.log(`Submitted value: ${input.value}`) // Get directly from the input
}
});
// Another example:
input.addEventListener('input', e => {
// Easy way to get the value of the element who trigger the current `e` event
console.log(`Input updated: ${e.currentTarget.value}`)
});
<form>
<input type="text"/>
<input type="submit"/>
</form>
I'd like to set an input that users can type only numbers and one dot(ex number.number(8 digits)) using regex.
// component A
<Input
name="password"
value={this.props.password}
onChange={this.props.onChange}
/>
.
// component B
state = { password : '' }
handleChange = (e) => {
const value = e.target.value;
const regexAllowOneDot = /\d+(\.?\d{0,8})/;
if(regexAllowOneDot.exec(value) !== null) {
this.setState({
password: regexAllowOneDot.exec(value)[0]
})
}else {
this.setState({
password: ''
})
}
}
<ComponentA
password={this.state.password}
onChange={this.handleChange}
/>
.
It works when type of the input is "text" but it doesn't work when the type is "number".
so, When the type is "number", I get these issues below(However, theses are totally solved when the type is "text")
When I check the developer tool from Chrome, the value of the input does not change (but e.target.value works)
Also, when I check through console.log(regexAllowOneDot.exec(value)[0]), It says null even though the value still has the one digit(length, like 1 or 2 or...)
I wonder why and how I can fix this or if you have a better solution.
ok, I got it now. You want to handle the keyPress event and stop it if necessary, like so:
keyPress = e => {
if (e.which === 46 && this.state.amount.includes(".")) {
e.preventDefault();
e.stopPropagation();
}
};
Then pass the function down to the child component and attach it to onKeyPress.
I have included a working fork of your code with the problem solved here: https://codesandbox.io/s/7wnz19156x?codemirror=1&fontsize=14
Note: to the best of my knowledge this question is not a duplicate question of the following:
HTML5: Why does my “oninvalid” attribute let the pattern fail?
HTML5 form required attribute. Set custom validation message?
How can I change or remove HTML5 form validation default error messages?
Overview
Given a field that:
Has pattern attribute set for validation, for example "[a-f,0-9]{4}" for a 4 character hex string input.
Has oninvalid set with setCustomValidity('...some message...') to define a custom validation message
Has oninput set with setCustomValidity('') to reset on input
Here is an example showing this:
/* jshint esnext: true */
const form = document.querySelector("#form");
const field = document.querySelector("#field");
const output = document.querySelector("#output");
form.addEventListener('submit', (e) => {
console.log("SUBMIT");
output.textContent = field.value;
e.preventDefault(); // Prevent default POST request
});
field.oninvalid = (event) => {
console.log("INVALID");
event.target.setCustomValidity('must be valid 4 hex characters');
}
field.oninput = (event) => {
console.log("INPUT");
event.target.setCustomValidity('');
}
Output: <span id="output">No output</span>
<form id="form">
<label for="field">Enter 4 character hex code: </label>
<input id="field" type="text" pattern="[a-f,0-9]{4}" autocomplete=off>
</form>
Validation works almost as desired, except when the user enters an invalid entry and then proceeds to try and edit it, where their following input states are still invalid:
At this point, neither the custom setCustomValidity message defined in oninvalid is used, nor the empty one defined in onInput.
Instead, as long as the field is in an invalid state and not blurred, the default Please match the requested format. message appears.
Question
What is going on here? Looking at the console, the oninput event is called each time, and therefore event.target.setCustomValidity(''); is called each time.
So why is it that we are still seeing the generic default validation message? Shouldn't setCustomValidity('') disable that?
An acceptable answer here should exhibit the following:
The parameter field is respected for validation.
Any validation message appears if and only if the user attempts to submit an invalid field and not when they modify the input immediately afterward.
The default Please match the requested format. message never appears at all.
It appears that this is a bug with Chrome 65 in windows.
using setCustomValidity('') in oninput should disable the default validation messages appearing on input.
The following workaround works for me:
/* jshint esnext: true */
const form = document.querySelector("#form");
const field = document.querySelector("#field");
const output = document.querySelector("#output");
const pattern = field.getAttribute("pattern");
form.addEventListener('submit', (e) => {
console.log("SUBMIT");
output.textContent = `User submitted: ${field.value}`;
e.preventDefault(); // Prevent default POST request
});
field.oninvalid = (event) => {
console.log("INVALID");
event.target.setCustomValidity('must be valid 4 hex characters');
}
field.oninput = (event) => {
console.log("INPUT");
event.target.setCustomValidity('');
event.target.removeAttribute("pattern");
}
field.onchange = (event) => {
console.log("CHANGE");
event.target.setAttribute("pattern", pattern);
}
Output: <span id="output">No output</span>
<form id="form">
<label for="field">Enter 4 character hex code: </label>
<input id="field" type="text" pattern="[a-f,0-9]{4}" autocomplete=off>
</form>
setCustomValidity is meant to be used when multiple inputs, in combination are invalid. That is why it has to be reset to the empty string manually after. Other wise the title attribute should be used.
Trying to hide the validation error after editing the input is understandable but it is against the HTML5 form philosophy. It is meant to be shown as long as the input is invalid.
Adding maxlength can help the user to not cross the upper limit.
If you really want your bullet points to be satisfied feel free to not use HTML5 form validation but something custom instead.
So the reason a tooltip is shown even when setCustomValidity is set to empty string is because the input element is still invalid as per pattern attribute.
<form id="form">
<label for="field">Enter 4 character hex code: </label>
<input id="field" type="text" pattern="[a-f,0-9]{4}" maxlength="4" minlength="4" autocomplete="off" title="must be valid 4 hex characters">
</form>
JS
const form = document.querySelector("#form");
const field = document.querySelector("#field");
const output = document.querySelector("#output");
form.addEventListener('submit', (e) => {
console.log("SUBMIT");
output.textContent = field.value;
e.preventDefault(); // Prevent default POST request
});
field.oninvalid = (event) => {
console.log("INVALID");
}
field.oninput = (event) => {
console.log("INPUT");
}
In putting together a small webapp, I'm trying to ensure that end users are unable to place invalid characters in a number field that can hold signed floats. I'm using Dojo to search on an applied CSS class (in this case, ogInputNumber) and set events on input, keyup, and blur.
Ideally, I would like the input to be type="number" and to only allow digits, a hyphen (for signed floats), and a period character to act as a decimal place. If a user includes more than one hyphen or period character, the JS should truncate that second invalid character and everything thereafter in the input. Unfortunately, the JS behaves differently depending on whether the input is type="number" or type="text".
For type="text", if I attempt to enter the text 2.6a, 2.6 is fine, but the a is caught on the input event and prevented from appearing in the input. This is the desired behavior, but I would like to have the input as type="number" so the number spinners appear and for ease of use with mobile devices (so the number keyboard is brought up by default).
For type="number", if I attempt to enter the text 2.6a, the 2.6 is allowed to remain, but as soon as a is typed, the entire field is cleared out. That will prevent any invalid characters, but it's annoyingly overzealous. I've replicated this behavior on Chrome, Firefox, IE11, and Opera.
Can anyone offer any suggestions as to why the JS operates differently between inputs with type="text" and those with type="number"?
HTML:
<p>
<label for="numberInput1">Text Input</label>
<input id="numberInput1" class="ogInputNumber" type="text" />
</p>
<p>
<label for="numberInput2">Number Input</label>
<input id="numberInput2" class="ogInputNumber" type="number" />
</p>
JS:
// Checks number input fields for proper formatting
require(["dojo/domReady!", "dojo/on", "dojo/query"],
function (ready, on, query) {
query(".ogInputNumber").forEach(function (node) {
// Replace all the non-numeric, non-period, and non-hyphen characters with nothing while the user is typing
on(node, "input, keyup", function () {
this.value = this.value.replace(/[^\d\.-]/g, '');
});
// When the user leaves the input, format it properly as a signed float (or zero if it's something weird)
on(node, "blur", function () {
try {
if (this.value) {
this.value = parseFloat(this.value).toString();
} else {}
} catch (error) {
this.value = 0;
}
});
});
});
Working JSFiddle: http://jsfiddle.net/etehy6o6/1/
I think that's the default behavior of number input type, but I'm not sure. It's logical to think the input should not let the user put anything that is not a number, so it clears all the value before you can fire your keyup event.
So to keep the last valid value declare a variable outside the scope of your event and set it to the replaced value that was not cleared because invalid key input.
Using the code in your Fiddle:
Edited because addressed bug in comments
HTML
<!-- I asigned default values to test other scenarios -->
<p>
<label for="numberInput1">Text Input</label>
<input id="numberInput2" class="ogInputNumber" type="text" value="3.1416" />
</p>
<p>
<label for="numberInput">Number Input</label>
<input id="numberInput" class="ogInputNumber" type="number" value="3.1416" />
</p>
Javascript
// Checks number input fields for proper formatting
require(["dojo/domReady!", "dojo/on", "dojo/query"],
function (ready, on, query) {
query(".ogInputNumber").forEach(function (node) {
var validValue = this.value;
// Replace all the non-numeric, non-period, and non-hyphen characters with nothing while the user is typing
on(node, "input, keyup", function () {
if (this.value == '' && validValue.length > 1) {
this.value = validValue;
}
this.value = this.value.replace(/[^\d\.-]/g, '');
validValue = this.value;
});
// When the user leaves the input, format it properly as a signed float (or zero if it's something weird)
on(node, "blur", function () {
try {
if (this.value) {
this.value = parseFloat(this.value).toString();
} else {}
} catch (error) {
this.value = 0;
}
});
});
});