0

I have a simple Angular app (just learning) that I am trying to use with Angular Material. To just get something up and running I want to use <md-chips> to add an array of attributes to a product model. Here's a snippet from the HTML:

// EXTRACT FROM VIEW
<md-content class="md-padding" layout="column">
    <form name="productForm">
        <section class="md-padding" layout="column">
            <md-input-container flex>
                <label ng-show="productForm.category.$pristine">e.g. Umbrella</label>
                <input name="category" ng-model="product.category" ng-minlength="3" ng-maxlength="80" required>
            </md-input-container>
        </section>

        <section class="md-padding" layout="column">
            <md-chips ng-model="product.attributes">
                <input type="text" placeholder="e.g. Size">
            </md-chips>
        </section>

    </form>
</md-content>

And here's a snippet from the JS. Everything is working - except I am expecting the $scope.productAttrsLen variable to update within the $scope.$watch('product') call. The ProductService.product model updates .... but the $scope.productAttrsLen doesn't. However - when I also run a $scope.$watchCollection on product.attributes then $scope.productAttrsLen does update. Can anyone explain why, and how I can accomplish this all within the $scope.$watch('product'...) call?? I've commented the code below:

// EXTRACT FROM CONTROLLER
myApp.controller('newProductController', [
    '$scope', '$log', 'ProductService',
    function (
        $scope, $log, ProductService) {

        $scope.product = ProductService.product || {};
        $scope.product.attributes = [];

        function getProductAttsLen() {
            return _.size($scope.product.attributes);
        }
        $scope.productAttrsLen = getProductAttsLen();

        // when I only include the following code, 
        // the product object updates (including the attributes)
        // but productAttrsLen does not update.
        $scope.$watch('product', function (product) {
            ProductService.product = product;
            $scope.productAttrsLen = getProductAttsLen();
        });

        // However, when I ALSO include the following code, the productAttrsLen
        // does get updated. Why?? Ideally, it would all get sorted in the 
        // $scope.$watch('product'...) function call.
        $scope.$watchCollection('product.attributes', function (attributes) {
            $scope.productAttrsLen = getProductAttsLen();
        });

}])
The Pied Pipes
  • 1,425
  • 2
  • 16
  • 29
  • 1
    the title is misleading here. `$scope.watch()` doesn't update anything; it may call a function that does some updating, but that's not the same thing. – Claies Oct 11 '15 at 20:29
  • 1
    Where is the update to `product` being triggered? Just changing, or completely replacing, `product.attributes` won't trigger the `$watch` listener because the reference to `product` is still the same object. See http://stackoverflow.com/a/19455564/1901857 – Rhumborl Oct 11 '15 at 20:41
  • 1
    looking at this code, the `$scope.product.attributes = [];` line will cause your function to point to an empty array, not to the `attributes` property of `product`. even if the product is updated, the function won't trigger, because the array didn't change. – Claies Oct 11 '15 at 20:42
  • thank you both. @Claies for spotting an error (needed to put ```$scope.product.attributes = $scope.product.attributes || [] ````) and @Rumbori for letting me know about the deep watch technique. Both v helpful. – The Pied Pipes Oct 11 '15 at 20:46

0 Answers0