Reputation: 4908
Is there any particular reason why this deep watch doesn't fire?
http://plnkr.co/edit/6FxMS4RlfljBMkprZYQs?p=preview
Could it be that watch doesn't check angular attributes? Ie. those begging with $? If that's the case, is there any way to watch on validity change, and not just on the form, but on any of the inputs?
Upvotes: 1
Views: 15437
Reputation: 1686
Maybe a bit later but i have found another way. Using:
$scope.$watchCollection
in particular you can watch the myForm variabile inside the scope using $watchColletion and update your buttons or anything you need.
$scope.$watchCollection(function () {
if ($scope.myForm)
return $scope.myForm;
}, function () {
if ($scope.myForm)
if (($scope.myForm.$invalid == true))
$scope.formValidityChange(true);
else
$scope.formValidityChange(false);
}, true);
this will check all the variabiles that change inside the form and you will update the controller. i think u can also check what is changed by comparing the two objects maybe this can be more difficult.
Upvotes: 2
Reputation: 4908
The solution is to watch on .$error, which works just fine. See http://plnkr.co/edit/6FxMS4RlfljBMkprZYQs?p=preview
It's basically like watching on form's valid, except that this one updates everytime any validity inside changes.
Credit goes to https://stackoverflow.com/users/490498/jonathan-rowny
Upvotes: 5
Reputation: 565
$watch watches changes on the $scope. Since your input is not bound to the same $scope property that is being watched, your watch listener is only called once, on initialization.
To give a little better idea of how $watches, binding and $scope works, here is what your scope looks like (actually, your scope is empty, because you haven't written anything into it, but this is what it WOULD look like based on your template):
{
shizzle: { // <--- This is the property you're watching
$valid: false,
whatev: {
valid: false
}
},
whatev: "" // <--- This is the object that is changing when you type into the <input>
}
As you can see, shizzle is being watched, but doesn't change, so the watch listener is only fired once.
Here is an edited version of your plunker that binds the watcher to the input's model, and logs all changes, for demonstration:
http://plnkr.co/edit/NrE5blIbyBcsOjC2vIrk?p=preview
EDIT: If your goal is to watch the $valid attribute, which angular is setting, then you can change this line:
scope.$watch(attrs.name, function(newVal, oldVal) {
console.log(newVal);
}, true);
to this:
scope.$watch("shizzle.$valid", function(newVal, oldVal) {
console.log(newVal);
}, true);
Upvotes: 0