With AngularJS's $scope.$watch, you are able to monitor scope values for changes. This can be useful for validation of user input, as an example.
The watch method of Angular scopes is a really handy way to monitor values for changes when developing applications. To show this, we're going to look at a simple form.
You can see here we've got a watch controller for our entire body right here. We've just got a simple bootstrap based form here. Really, the only field we're going to be concerned with here is this password form.
We're mimicking a create account screen here. It's probably not a very good one since we don't have a password verification field but simplicity's sake it's easier this way.
The important part of this is that the ngModel for this input field is user.password. That means it's going to map to a property named password on an object named user on our scope.
The first thing I want to show here is here's our controller. You can see we're setting it up as part of the app there. Basic definition here. Passing in the scope, and then we can ignore these other two functions for now.
If we look at scope.watch user.password so that matches our ngModel expression here. We're going to tell Angular that we want to monitor user.password and be notified of any changes.
You can see that the arguments to our function are newVal and oldVal.
The first thing I want to show is the type of values you get in this. If you were to log out newVal and oldVal, save this file, and then refresh our page here you can see that we get called immediately when the app starts up. Both values are undefined.
That's one thing to keep in mind is that initially when your watch function starts up it's likely going to receive undefined for both the new value and the old value because we've not actually set anything in here.
If I click into this field and then enter a letter, now we can see that the old value is still undefined because that's what we had last time it was ran, but the new value is now "s."
If I use another key, we can see that now we have "sw." We used to have "s," and on and on and on.
You can see how that works.
To actually do something useful for this, let's get rid of this and then we'll add some code here.
In this case what we're going to do, we're just going to guard against this. When we get those undefined values we're going to just go ahead and bail out. That won't be the case 100 percent of the time but most of the time in these watched functions that's what you're probably going to want to do because you're interested in when the value actually changes and not when it's just empty.
In this case, what we're going to do, as long as we have gotten a valid value we're going to initialize a array called reqs, which is sort for requirements. Then we're going to use these functions up here that we defined to check our password for some properties.
We're going to check to make sure it's long enough, which you can see here we're just enforcing a password that is more than four characters long. Then we're going to enforce that it has a number, as well. We're calling this function.
In either case, if either one of those verification functions returns false we're going to add a message to the requirements.
Finally, we're going to set this show requirements variable based on the length of our array. If we've added at least one of those items to the array, that's going to be true. If it's empty it's going to be false.
If we go look at our markup here, you can see that there's actually another div below the form. I've got the ngShow set to showReqs so it's only going to show up if we have some of those requirements. Then we're going to iterate over those requirements and just write them out.
If I go over here and minimize this some and then refresh the page, we can see that once we start typing in here we first get both of these warnings, right? Because we have one character so it's too short and I typed a letter so it doesn't have any numbers.
I can type another character. Still too short. Now if I type a number it's going to get rid of that number message because we've met that requirement. Then if I go ahead and add a couple more characters the last warning goes away because we've now met the minimum length requirement of five.
For the most part, that's really all there is to the watch functionality. You're comparing the new value from the value it had before. You may want to react to that in some way based on how something changed.
In a lot of cases, you're just going to want to react to the new value and run some logic based on that new value.
There is a third argument to the scope.watch method, which is the object equality argument. In our case, since we're just using a string property, user.password is just a string, that's really not going to make any difference to us.
But if we were to set this to true and we were watching an actual object, having that set to true would make it so that Angular compares those objects and essentially looks for loose value based equality rather than reference equality.
If you had an object with foo and bar properties and replaced it with another object with foo and bar properties that had the same values this would not see it as a different value if you had true set here.
If you don't have this argument it's going to do an actual reference check and make sure that it's the same object in memory.