I'm creating a directive to exclude a hidden input element from validation: http://plnkr.co/edit/Vnwvq2AT7JpgTnoQwGh9?p=preview
app.directive('shownValidation', function() {
return {
require: '^form',
restrict: 'A',
link: function(scope, element, attrs,form) {
var control;
scope.$watch(attrs.ngShow,function(value){
if (!control){
control = form[element.attr("name")];
}
if (value == true){
form.$addControl(control);
}else{
form.$removeControl(control);
}
});
}
};
});
The idea here is if the element is hidden, I will remove the control from the Form so that it will not affect the other input validity. It works fine when I call form.$removeControl(control);
, you can test that in the demo by removing the firstname and clicking on the button to hide the field.
But when I click the button again, the form validity is still true even though the firstname is invalid (empty)
I also tried adding form.$setValidity(form.$valid && control.$valid)
=> the validity state is updated as expected but when I type into the firstname, the validity is still false.
My question is how to solve this problem? Thanks for any replies.
Update:
Thanks to @Michael's answer. Here is the working solution:
app.directive('shownValidation', function() {
return {
require: '^form',
restrict: 'A',
link: function(scope, element, attrs, form) {
var control;
scope.$watch(attrs.ngShow, function(value) {
if (!control) {
control = form[element.attr("name")];
}
if (value == true) {
form.$addControl(control);
//Add a forEach to manually update form validity.Thanks to @Michael's answer
angular.forEach(control.$error, function(validity, validationToken) {
form.$setValidity(validationToken, !validity, control);
});
} else {
form.$removeControl(control);
}
});
}
};
});
Working plunk
If the control is removed angular updates the validity (from the sources):
form.$removeControl = function(control) {
if (control.$name && form[control.$name] === control) {
delete form[control.$name];
}
forEach(errors, function(queue, validationToken) {
form.$setValidity(validationToken, true, control);
});
arrayRemove(controls, control);
};
If you add the control angular did not update the validity (from the sources):
form.$addControl = function(control) {
// Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored
// and not added to the scope. Now we throw an error.
assertNotHasOwnProperty(control.$name, 'input');
controls.push(control);
if (control.$name) {
form[control.$name] = control;
}
};
so we have to do this manually. I guess this way:
if (value == true){
form.$addControl(control);
angular.forEach(control.$error, function(validity, validationToken) {
form.$setValidity(validationToken, !validity, control);
});
}else{
form.$removeControl(control);
}
}
It seems you are hiding the element using ng-show
and thus not submitting the input along with the form.
In this case, we can use ng-if
directive in the view in order to remove the element on the fly.
This would remove the element and it's validity too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With