Difference between checkValidity & validity - javascript

I've noticed there are 2 ways for an input element validation:
element.checkValidity().
element.validity.valid.
I understand that validity is an object while checkValidity is a function but I don't understand when should I use either one of them and what is the key difference between them.

HTMLSelectElement.checkValidity():
The HTMLSelectElement.checkValidity() method checks whether the element has any constraints and whether it satisfies them. If the element fails its constraints, the browser fires a cancelable invalid event at the element, and then returns false.
ValidityState.valid:
Is a Boolean indicating the element meets all constraint validations, and is therefore considered to be valid.
So the main difference is that checkValidity() will also fire an "invalid" event. If you just want to know whether the value is valid, use ValidityState.valid. But if you want to change the form state to invalid, use checkValidity().

Related

How to programatically set invalid value in input type=number?

I want to set an invalid value to input element with type=number.
I'm writing unit tests for my component which uses input with type=number and it behavior depends on whether the input is empty or not not. Note that I'm treating invalid values like '1.2.3' as not empty, even though it's value property is ''.
While it's possible for user in browser to enter invalid values like '1.2.3' I cannot simulate it for my tests.
// let input be HTMLInputElement
input.value = '1.2.3';
console.log(input.value); // ""
console.log(input.validity.valid); // true
I would like to somehow set invalid value for my input type=number, so I could test if my component's logic is valid.
You can use
input.setCustomValidity("dummy value");
to make input.validity.valid return false.
For an idea of why this works, see this CodePen. What it does is it sets an error message that indicates the input is invalid. To make it appear valid once again, use
input.setCustomValidity("");

ReactiveForms valueChanges in dom vs component

I'm wonder if there's a way to know the difference whether valueChanges on a FormControl was triggered from the dom or the component itself. My use case is I need to do stuff() when the user changes the value, but I don't want to do stuff() if the value changed as a result of something else. Any thoughts?
with the control ".touched"
EXAMPLE:
YourModelForm.get('YourField').touched
the value becomes true when the user enters a value (first click on the field, enter the value, tab or click out of the field).
I tried with a call rest and the value remains to false, try it if you can possibly it works for your situation. :-)
Thanks to #Nobady, who inspired the idea. I found there's actually an option for setValue on the formControl called emitEvent. Using this, I can make it so if I update the value programmatically I can bypass the valueChanges getting called.

HTML5 validation: JavaScript weirdness with willValidate

OK this is a weird one. I'm sure I'm missing something obvious.
http://jsfiddle.net/wVp8j/
HTML:
<form>
<input type='text' required />
<button>check field validity</button>
</form>
JS:
var field = document.querySelector('input[type=text]');
document.querySelector('button').addEventListener('click', function() {
alert('Validates: '+field.willValidate);
alert('Value missing: '+field.validity.valueMissing);
}, false);
If the form is submitted with the field left blank, submission is suppressed, as you'd expect, but the first alert, checking the field's validity state, gives true. Why?
To contradict this further, the second alert confirms there's a problem with the field and also gives true, as expected.
What am I missing?
[Sidenote: MDN seems to think willValidate is a method, not a property.]
[EDIT]
As the commenter below points out, willValidate says whether the field is a candidate for validation, not, despite its misleading name, whether the field will validate.
Which presumably means the only means of telling whether a field will validate, should the form be submitted, via JS, is to iterate over its validity object and see if any flag is set to true.
[EDIT 2]
Turns out you can just check validity.valid on a field, even though the valid flag doesn't show up if you console.log the entire validity object. This would appear to be the way, therefore, to find out whether a field will hypothetically validate.
willValidate is a property that says whether or not an input can be validated, not if it is valid or not. The only time that willValidate is false is if the input element is disabled or the like.
See http://www.html5rocks.com/en/tutorials/forms/constraintvalidation/#toc-willValidate
Use field.validity.valid instead to check for validity.
http://jsfiddle.net/3xFua/
(function() {
var field = document.querySelector('input[type=text]');
document.querySelector('button').addEventListener('click', function() {
console.log('Validates: ', field.validity.valid);
console.log('Value missing: ', field.validity.valueMissing);
}, false);
})();
The documentation suggests using .checkValidity() which
Method Description
checkValidity() Returns true if the element's value has no validity problems; false otherwise. If the element is invalid, this method also causes an invalid event at the element.
while (as #soktinpk's answer correctly states) .willValidate simply flags it as available for validation, not passing validation.
Thus I recommend using this:
function() {
alert('Validates: '+field.checkValidation());
alert('Value missing: '+field.validity.valueMissing);
}
off-topic, alert is a terrible debugging tool. Consider using console.log or debugger;

What does the jQuery function $('#myelement').is('*') do?

What does the following code do:
$('#myelement').is('*')
What does the asterisk signify? Since there is only one element, #myelement, I can't understand the point of using is(), which checks if an element matches a set of elements?
This is some seriously existential JavaScript.
$('#myelement').is('*')
It will fail whenever #myelement doesn't exist, and return true otherwise.
Basically check to see if an element exists or not. Not the best method...
is checks the element fits the criteria. In this case, "*" means all elements.
So, it simply returns true if the previous selector returns anything.
Take a look here for an example: http://jsfiddle.net/b7DwB/
http://api.jquery.com/is/
Pretty much what it does well from my understanding of it at least, and how I tend to use it. Is return true or false on whatever its called on.
Example I have a checkbox that I want to make sure is checked before I submit my form via AJAX I would do something like
if( $('input#tosCheck').is(':checked') ){
/*its checked submit form*/
}else{
alert('Error');
}
All in all the link to the API from jQuery better describes it then I ever could, but I wanted to at least share an example of use to help you gauge some idea.
Can't say I've ever seen that jQuery code used before, but it seems to be a poor way of checking for the existence of an element. Since * is the universal selector, the expression in question will always return true if #myelement exists, otherwise it will return false.
I say this is a "poor" way of checking the existence of an element because you can simply check the length of the jQuery object instead:
$('#myelement').length > 0
I haven't done any testing, but I assume the above is faster since it doesn't have the overhead of the is() function call.

jQuery ".triggerHandler()" vs. ".trigger()" when multiple elements are selected

The jQuery ".triggerHandler()" mechanism, unlike ".trigger()", only operates on the first element referenced by the jQuery object for which it's called. In other words,
$('.all-over-the-page').triggerHandler("readjust");
will only call the "readjust" handler for the first element with class "all-over-the-page", even if there are many elements on the page with that class. The ".trigger()" method, on the other hand, would affect all of them.
I realize that I can use ".each()" to get around this (or simply write my own substitute that does that for me), but is there some rationale for why the two are different in this respect? It kind-of makes no sense to me. (I understand of course that it almost certainly can't be changed now.)
edit to clarify:
It's probably easier to understand why I'm scratching my head over this if I provide a context in the style of code I've actually got. When I put together code for various "widget" features on a page, that often involves event handlers. A good example is a form of some sort that's got some fields whose relevance is controlled by a checkbox, or radio button, or selector. A common instance of that is the "Shipping Address" checkbox that shows up on a zillion e-commerce sites: if the checkbox is checked, the shipping address is disabled and the billing address is used.
Now consider that some other code may, for its own reasons that are totally independent of the checkbox-control widget, actually do things to the form that may include updating checkbox settings programmatically. In that case, that other widget code may want to use "triggerHandler()" to tell any widgets, "hey I've updated some stuff, so you might want to re-check the current status and adjust if necessary."
Thus, if ".triggerHandler()" would operate on all selected elements, I could use:
$theForm.find('input, select, textarea').triggerHandler('change');
and all those handlers could run and do whatever they need. As I said, it's easy enough to write:
$theForm.find('input, select, textarea').each(function() {
$(this).triggerHandler('change');
});
"...is there some rationale for why the two are different in this respect?"
I think the idea is that triggerHandler() is meant to be a way of invoking the function you as a handler as though it was any other function.
As such, they made triggerHandler() so that the function is only invoked once, it returns the actual return value of the function, and it doesn't affect the DOM with bubbling or default behaviors.
Of course the function may break if they changed the this value to something other than a DOM element, so they just use the first element matched.
If you're wanting to simply use your function, then I'd probably just keep a reference to it and invoke it directly, or as the argument to .each().
$('.element').each( handler_func );
...as long as you don't need the event object.
EDIT: Or if you want the values returned from the invocation, use .map() instead:
var return_values = $('.element').map( handler_func );
EDIT: With respect to the example provided in the updated question, a good solution may be to take advantage of the extraParameters capability of the trigger()[docs] method so that you can tell the handler to preventDefault() and stopPropagation().
$('.elememts').bind( 'click', function( e, was_code_triggered ) {
if( was_code_triggered ) {
e.preventDefault();
e.stopPropagation();
}
// your code
});
// ...
$('.elememts').trigger( 'click', true ); // pass "true" to let handler know
// it wasn't a DOM event
From the .trigger() docs:
"Note the difference between the extra parameters we're passing here and the eventData parameter to the .bind() method. Both are mechanisms for passing information to an event handler, but the extraParameters argument to .trigger() allows information to be determined at the time the event is triggered, while the eventData argument to .bind() requires the information to be already computed at the time the handler is bound."

Categories

Resources