It looks like when an input element is initially loaded, its validity is not evaluated right away. For example, if my HTML looks like this...
<input type="text" value="ABC" minlength="5">
In JavaScript it appears that the input is valid and not too short, despite the value attribute being set to a length less than 5. For example:
const input = document.querySelector("input");
console.log(input.validity.valid); // true
console.log(input.validity.tooShort); // false
Only when the user makes a change in the input can we get a true reckoning of the input's validity.
Is there any way to force the input to evaluate its actual validity on load, even if the user has not yet touched the input?
See example: https://jsfiddle.net/t5afujkn/3/
I guess the reason is your default value is not checked from <input> directly at load as it probably does not trigger a check for the default values.
You can add another check condition in your js as below:
{
const displayObj = {
valid: input.validity.valid,
tooShort: input.validity.tooShort
};
if (input.value.length < 5) {
displayObj.valid = false;
displayObj.tooShort = true;
document.querySelector("p").textContent = JSON.stringify(displayObj);
}
}
or maybe you can also try to put the if condition somewhere outside the button call.
Also I did an update in JSFiddle; not sure if you can see it: https://jsfiddle.net/2Lhp96ct/6/
Related
I want to get one-time information from the input control when value is empty and when value is not empty
Right now I'm using onChange like below:
<Input onChange={onChangeValue()} />
But this onChangeValue method is running every time when I type into the input, but I want two times information, first when value from input is empty and second when value from input is not empty.
Can someoone tell me what can I do this?
You can put some logic before your onChangeValue() function that checks the input value's length and then calls onChangeValue():
beforeOnChangeValue = function() {
if(arguments[0].target.value.length <= 1) return onChangeValue(arguments)
}
<Input onChange={beforeOnChangeValue} />
This way the onChangeValue() function will only be called when the input is either emptied or when the first character is put in
it seems like you're using controlled components (changing the value of the control on every key typing). I think based on your strategy that you could use a flag in the onChange handler like this
function onChange (evt) {
setIsEmpty(!!evt.target.value);
// Your code ...
}
Then you'll always know if the input is empty or not.
function Form () {
const [isEmpty, setIsEmpty] = React.useState(false);
// onChange here
return <Input className={isEmpty ? 'empty-class' : 'non-empty-class'} />
}
I have a javascript script that's supposed to detect whenever an html form input with type="time" has any value entered.
However, whenever I enter a partial value (for instance, type one number, instead of a full time with AM/PM), it doesn't detect the input as having a value.
In the below example, timeSelector is the input with type="time".
if (timeSelector.value == "") {
timeSelector.classList.add("empty");
} else {
timeSelector.classList.remove("empty");
}
Is there any way to detect this type of thing?
To clarify, since apparently I didn't ask my question clearly enough, I need to detect when a time input has something entered, even if that something is an invalid or incomplete input.
Well the problem with html5 inputs is they do not give the text in the input if it is not valid. So you can use checkValidity when the user removes focus from the element.
var checkInput = function() {
var value = this.value
var isValid = this.checkValidity()
if (!this.value.length && isValid) {
console.log('empty');
} else if (!this.value.length && !isValid) {
console.log('invalid time entered')
} else {
console.log('valid time entered')
}
}
var input = document.querySelector("input")
input.addEventListener("input", checkInput)
input.addEventListener("blur", checkInput)
<input type="time" />
Per the specification on Input Elements with type time ( HTML Spec ) :
The value attribute, if specified and not empty, must have a value that is a valid time string.
If the value of the element is not a valid time string, then set it to the empty string instead.
This means that input and change events don't occur until the entire time field has been filled out. Why? Because nothing really has changed.
You may think that you can circumvent this by using keydown or keyup events, but this is simply not the case.
The value is not changed and is therefore inaccessible until a full string that is capable of being parsed as a time is inside the time input box.
By filling in the below example you can see how the events fire. Notice the lack of value until everything is filled in.
let i = document.querySelector("input"),
on = type => i.addEventListener(type, function() { console.log(`${type}, value: ${i.value}`); });
on("keydown");
on("keyup");
on("change");
on("input");
<input type="time">
The only way to possibly get around the lack of a changing value is to set a default value as below:
let i = document.querySelector("input"),
on = type => i.addEventListener(type, function() { console.log(`${type}, value: ${i.value}`); });
on("change");
<input type="time" value="00:00">
However, with a default value there is a risk that the user will submit a time that isn't something that you'd likely want.
You could write some validation code to take care of this depending on the complexity of your functionality this may be possible.
Overall if this is something you need and the functionality is a bit more complicated than you think you can handle validating yourself, it would be best to either create your own time input interface from other input types, or to use a library or UI kit from a source that has already done the legwork.
If I have input[type=number], Chrome allows me to type not just numbers, but also characters like - (minus sign) - for negative numbers. And it seems you can actually type multiple of those - minus signs and dots, e.g.: ".....---888". And when that happens, in on-change event, property of event.target.value would be an empty string (because it's not a valid number). But I would like validation message to appear, telling user has to type an actual number.
So the question is: How do I read the actual value, the one that's being displayed in the input field, because it seems, sometimes it's not the same as event.target.value
I don't know if this matters - this is in a React app
You can use the event.target.validity.valid or even better the event.target.validity.badInput property to check if the value is valid.
(although badInput does not seem to be supported by IE)
But i would use the input event instead of the change event, because if the user enters invalid input when starting at an empty <input> element, the change event will not fire since the value is considered empty (due to it being invalid)
Alternatively, you could use the css :invalid selector and use it to show a message that is hidden (requires specific html structure)
input[type="number"] ~ span.message{display:none;}
input[type="number"]:invalid ~ span.message{display:block;}
Use a hidden input that mimics your [type=number] one:
var numberInput = document.querySelector('input[type=number]');
var dolly = document.querySelector('input[hidden]');
numberInput.addEventListener('keyup', (event) => {
if (event.key !== 'Backspace') {
dolly.value += event.key;
} else {
dolly.value = dolly.value.substr(0, dolly.value.length - 1);
}
console.log(dolly.value);
});
<input type="number">
<input hidden>
Obviously, you will need to do more processing for certain keys. This way you get the benefits of the number type and also maintain whatever crazy stuff the user puts in there.
I'm not sure about getting the value, but since you want to set a custom validation message, you can use input setCustomValidity property (see the docs here) and check if an input is valid using the validity.valid property. Here's my implementation.
var myInput = document.getElementById("my-input");
myInput.addEventListener("keyup", function (event) {
if (!myInput.validity.valid) {
myInput.setCustomValidity("I expect a valid number, darling!");
} else {
myInput.setCustomValidity("");
}
});
<form>
<label>Please provide me a number</label>
<input type="number" id="my-input" name="my-input">
<button>Submit</button>
</form>
update:
input[type=number] will always return empty if not number, use input[type=text]and check the value if Not-a-number using isNaN()
I need to check all the inputs to see if they are filled, in which case the submit button would become pressable and the user can submit their data safely:
unfilled = false;
$('.add-field').keypress(function(){
$('.add-field').each(function(){
if($(this).val() === ''){
unfilled = true;
} else {
unfilled = false;
}
})
console.log(unfilled);
});
This code works, but it has a strange twist; as the last empty input gains a character, it still returns true. If an input gains another character, only then it will return false. I am confused by this, as I understand that the .each() function is fired after a character has been added and the value of the input has been updated. Consequently, I do not see why it does not register that value.
You should set unfilled to false before entering the loop (but INSIDE the keyup).
In the loop you should only set unfilled to true when a field is emty and not set it to false again, otherwise you'll only know if the last field is filled in.
You could use filter and use keyup event instead for del keys:
DEMO
$('.add-field').keyup(function () {
var unfilled = !! $('.add-field').filter(function () {
return $.trim(this.value) === ""
}).length;
console.log(unfilled);
});
Here === means it is matching exactly the data types:
if($(this).val() === ''){
Replace it with == :
if($(this).val() == ''){
As far as I know, this is an 'issue' when using the KeyPress-event, because the Browser's UI Thread did not update the input field's value yet. Therefore the value currently is still 'empty' and thus true is returned; you can either use the KeyUp-event or try something like this: JavaScript keypress event get end value of textarea
I'm trying to write a generic function I can use with the jquery validation plugin that will make a field required based on the value of another field. Here's what I want to happen:
If Field 1's value is in a specified array of values (currently testing with "No", "n/a", and "0"), or is empty, do nothing. Otherwise, make Field 2 required.
Getting the value of Field 1 is the issue. I had no problem figuring this out with a text-type or <select> input, but I'm trying to get it to work with radios and having difficulty. Here is an excerpt from my code:
var value = $('[name="option"]').val(),
empty = ['no', '', 'n/a', '0'];
// If the input is not "empty", make the additional field required
if ($.inArray(value.toLowerCase(), empty) < 0) { // returns -1 if not found
required = true;
} else {
required = false;
}
This works for everything I need it to except radios, because it seems to read the value of the first radio, regardless of if it was checked or not.
The field that will trigger the "required" will either be one of the various text inputs (text, url, email, etc.), a <select>, or a single choice set of radios. No multiple choice. I'll be passing this function as a parameter to required in my jquery validation config for each field I want it to apply to. The name attribute of the "other" field that gets evaluated will be available to it.
Here's my demo so far, kind of ugly but there are notes: http://jsfiddle.net/uUdX2/3/
I've tried a bunch of different ways using is(':checked') and the :checked selector, but they have all failed. I removed them from the demo because they didn't work.
What do I need to get this working with radios and text-type or select inputs, without knowing which kind of input it will be?
Try this
var value = $('[name="option"]');
var type = value.attr("type");
if(type && type.toLowerCase() == 'radio')
value = value.filter(":checked").val();
else
value = value.val();
Working demo
Something like this:
var value = $('[type="radio"][name="option"]:checked, [type!="radio"][name="option"]', form).val() || '0'
Quite similar to Shankar's but does it all in the selector.
http://jsfiddle.net/infernalbadger/uUdX2/8/
It's not working when nothing is selected. Not sure what you want it to do when that happens?