angular-validation
angular-validation copied to clipboard
CheckValid not working as expected
when i call to check valid
this.checkValid = function(form) {
return !!(form && form.$valid);
};
Here . form.$valid = undefined
This is because i have an OPTIONAL control (user does not have to fill it in), but if they do it has a regEx validation.
so this input on the form also has a $valid = undefined - because the user NEVER entered the input and just skipped that part of the form.
The control is still ng-valid, the form is ng-valid (all inputs) - and none of the error messages show.
but checkValid returns FALSE - so the form does not submit
I'm not sure if I understand your description correctly, do you mind post your <Form> script here so that we can check your requirement.
I've worked out what the issue is ..
I have added an input like this
<input
ng-class="{focus:form.optionalNumber.$focus===true}"
ng-attr-type="text"
id="optionalNumber"
name="optionalNumber"
autocomplete="off"
pattern="\d*"
ng-model="model.optionalNumber"
maxlength="11"
ng-focus="form.optionalNumber.$focus=true"
ng-blur="form.optionalNumber.$focus=false"
initial-validity=true
validator="optionalNumber"
invalid-callback="invalidMsg(message)" />
The validator looks like this
optionalNumber: function(value) {
if(!value || value.length===0) {
return true;
}
var regexp = expr.formattedNumber;
return regexp.test(value);
},
The button submit calls this function
submit(form, state) {
let isValid = this.$validationProvider.checkValid(form);
if (isValid) {
return this.save(state);
}
console.log('Invalid Form');
this.$scope.form.submitted = true;
this.scrollToFirstError();
}
The issue is that because that the input is optional - so the user never has to enter a value and can skip the form (so it never moves from $pristine and the $watch never fires because the user does not alter the value. This means that the $valid and $invalid values on the form never fire but the form input is added to the $pending array (for validation) - this means that the $invalid and $valid properties on the form are "undefined"
So to combat this added the initial-validation=true - so that the initial state would be set and if the user did nothing then the input would still be valid. However this does not work.
on line 687 of angular-validation.js you have this code
/**
* Set initial validity to undefined if no boolean value is transmitted
*/
var initialValidity = void 0;
if (typeof attrs.initialValidity === 'boolean' ) {
initialValidity = attrs.initialValidity;
}
The issue here is that typeof attrs.initialValidity ALWAYS === 'string' because you are reading it from attrs so it will never be a boolean, it doesn't matter if you pass
initial-validity=true
initial-validity="true"
initial-validity="{{someConst}}" . // where the const is true
initial-validity="{{someBinding}}" // where the binding is to a variable that is true
When you inspect attrs..initialValidity its still a string, so the initial set up of the state is never set and so the optional model property validation remains "undefined" and the check fails.
there is a possible fix
Suggestion:
If you instead add a check for 'true' and 'false' when init initialValidity in your code...
if (typeof attrs.initialValidity === 'boolean' || attrs.initialValidity === 'true' || attrs.initialValidity === 'false') {
initialValidity = attrs.initialValidity;
}
THEN it will work as expected ....
A possible solution I use without forking the project for now is a custom directive that does the initialization of the ngModel field validity.
export const ngModelInitialValidityDirective = ($parse) => {
return {
restrict: 'A',
require: 'ngModel',
link: (scope, element, attrs, ngModelCtrl) => {
const initialValidity = $parse(attrs[directiveName])(scope);
if (_isBoolean(initialValidity)) {
ngModelCtrl.$setValidity(ngModelCtrl.$name, initialValidity);
}
},
};
};
ngModelInitialValidityDirective.$inject = ['$parse'];