Angular - $watch, $apply

Show the effect of $watch and $apply.

HTML

<script src="http://code.angularjs.org/angular-1.0.1.js"></script>
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css">
<body ng-app="myApp" ng-controller="myCtrl">

    <h3>Plain Angular</h3>
    <button ng-click="addQty(+1)">Add 1</button>
    <button ng-click="addQty(-1)">Subtract 1</button>
    <p>{{theArray.length}} items, total qty is {{getTotalQty()}}</p>
    
    <h3>Custom Directive</h3>
    <my-dir by-ref-arr="theArray" >
    </my-dir>
</body>

JavaScript

// the main (app) module
var myApp = angular.module("myApp", []);

// add a controller
myApp.controller("myCtrl", function($scope) {
    $scope.theArray = [
        { item: "Oranges", qty: 1 },
        { item: "Bananas", qty: 2 },
        { item: "Grapes", qty: 3 },
        { item: "Apples", qty: 4 }];
    $scope.addQty = function(inc) {
        for (var i = 0; i < $scope.theArray.length; i++) {
            $scope.theArray[i].qty += inc;
        }
    }
    $scope.getTotalQty = function() {
        var sum = 0;
        for (var i = 0; i < $scope.theArray.length; i++) {
            sum += $scope.theArray[i].qty;
        }
        return sum;
    }
});

myApp.directive("myDir", function() {
    return {
        restrict: "E",
        template: "<button></button>",
        replace: true,
        scope: {
            byRefArr: "="
        },
        link: function(scope, element, attrs) {
            
            // when user clicks, add 1 to the quantity of the first item
            element.click(function() {
                if (scope.byRefArr && scope.byRefArr.length > 0) {
                    scope.byRefArr[0].qty += 1;
                    scope.$apply("byRefArray"); // << ** need this to update
                }
            });
            
            // when array changes, update text in directive
            scope.$watch("byRefArr", function(oldVal, newVal, scope) {
                var sum = 0;
                for (var i = 0; i < scope.byRefArr.length; i++) {
                    sum += scope.byRefArr[i].qty;
                }
                element.text("Sum is " + sum + " click me to increase");
            }, true); // << ** set to true to compare by value not by reference
        }
    }
});