ajmajmajma
ajmajmajma

Reputation: 14226

Angular, watch $scope for changes

I am trying to watch a scope so I can have a function re run each time, and it does not seem to be working how I immagined it would.

so I just have

 $scope.user = userFactory.getUser();

My user being pulled in from a factory

And then later in a click function I change it to something else by having the user click a button like so

 $scope.swapUserTest = function(){
  $scope.user = {'name' : 'new'}
}

And then I'm trying to just watch if it changes - which right not is just in the click, in the future it will be from multiple differnt things so I would like a watch over it so whenever it changes my function fires. Something like this :

$scope.$watch($scope.user, function() {
  console.log("changed")
});

So I was assuming, whenever $scope.user changed this would fire, but it seems to only be firing when it first enters the controller form the factory. Could use some guidance here. Thank you!

Upvotes: 1

Views: 3880

Answers (2)

Rainer Plumer
Rainer Plumer

Reputation: 3753

To watch a property of a scope, set it as the first parameter for the $watch function. Note: when you watch an object, then your watch gets called only when the entire object changes, not when a property of that object changes. E.g:

$scope.user = {"username": "john", "email": "[email protected]"};
$scope.$watch("user", function(user) {
    console.log("users email now is:", user.email);
});

$timeout(function() {
    $scope.user = {"username": "jack", "email": "[email protected]"};
}, 1000);

$timeout(function() {
    $scope.user.email = "[email protected]";
}, 2000);

//  after one second console outputs
// [email protected]
//after 2 seconds ... nothing, even though user object's email has changed.

To "deep watch" an object, set the third parameter of your $watch to be true. $watch("property_name", callback_function, true);

Or when you want to watch a specific property of an object, use

$scope.$watch("user.email", function(email) {
    console.log("user.email watch called with:", email);
});
/* 
outputs both 
user.email watch called with: [email protected]
users.js:60 user.email watch called with: [email protected]
*/

Upvotes: 2

sma
sma

Reputation: 9597

You can either specify the property of an object:

$scope.$watch('user', function(newValue, oldValue) {
    // do something
});

or you can specify a function that returns the value you're watching:

$scope.$watch(function () {
    return $scope.user;
}, function(newValue, oldValue) {
    // do something
});

Upvotes: 5

Related Questions