39

I'm implementing a shopping cart and want to store the data in localStorage. I want to watch the variable $scope.cart for change so that I can update the localStorage

The cart variable looks like this:

[{'name':'foo', 'id':'bar', 'amount': 1 },...]

This is the code for the watch.

$scope.updateCart = function(){
    localStorageService.add('cart',JSON.stringify($scope.cart));
    alert('cart updated');
};

$scope.$watch($scope.cart, $scope.updateCart(), true);

This is the HTML where the user changes the model.

<li ng-repeat="item in cart">
  {{item.name}} <input type="text" ng-model="item.amount">
</li>

With the following code, the updateCart() method is never triggered. I'm not sure what I'm doing wrong. I check that the $scope.cart variable did change, but the update was not triggered.

3 Answers 3

41

$watch only evaluate string or function parameter in its first argument. Change your $watch like this :

$scope.$watch('cart.name + cart.id + cart.amount', $scope.updateCart());

OR

$scope.$watch('cart', $scope.updateCart, true);

See reference API

Sign up to request clarification or add additional context in comments.

5 Comments

Isn't true unnecessary in the first example?
$scope.updateCart will never trigger if you pass it in with parentheses as you would pass the result of the function to the $watch which would be undefined in this case. The correct way is: $scope.$watch('cart', $scope.updateCart, true);
cart is an array of objects, it does not have properties like amount
@SKuijers I guess that was fixed in this edit: stackoverflow.com/revisions/17419684/3
@TheRedPea yep it seems fixed. Thanks to rubensMaruizzo for the edit
29

It is a common mistake to use a variable as the first parameter to the watch expression.

For $scope.cart, you should use the string cart:

$scope.$watch('cart', function () {...}, true)

AngularJs has a new watch method, $watchCollection. It is basically the same as $watch with the object equality option set to true, to watch for a change in a property or an array item.

$scope.$watchCollection('cart', function () {...});

Documentation: $watchCollection.

2 Comments

$watchColletion saved me, when pushing / removing items from an array. Thanks!
It's unclear what kind of change the OP wanted, but as seen here $watch(.., .., true) detects even more changes, namely this type of change: $scope.cart[0].name= "Foo Bar";
1

try to change

$scope.$watch($scope.cart, $scope.updateCart(), true);

to

$scope.$watch('cart', $scope.updateCart(), true);

$watch only evaluate string or function parameter in its first argument

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.