<!DOCTYPE html>
<html>

  <head>
    <link rel="stylesheet" href="style.css">
	  <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
  <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js"></script>
    <script src="script.js"></script>
    <meta charset="utf-8" />
     
    <title>
    Scope $watch() vs. $watchCollection() In AngularJS
    </title>
     
    <style type="text/css">
    
    h1, h2 {
      font-size: 16px;
    }
     
    a[ ng-click ] {
    cursor: pointer ;
    text-decoration: underline ;
    }
     
    </style>
  </head>
  <body ng-app="Demo" ng-controller="AppController">
 
<h1>
Scope $watch() vs. $watchCollection() In AngularJS
</h1>
 
<p>
<a ng-click="changeDeepValue()">Change Value on Property (Element) in Collection</a>
&mdash;<br>
<a ng-click="changeShallowValue()">Add Property (Element) to Collection</a>
&mdash;<br>
<a ng-click="rebuild()">Rebuild</a>
&mdash;
<a ng-click="empty()">Empty Collection</a>
&mdash;
<a ng-click="clear()">Clear Log</a>

<h2>
$watch( collection ) Log
</h2>
Normal watch is only triggered if the value changes. E.g. an
array is still an array to it, regardless how many elements are in it.
 
<ul>
<li ng-repeat="item in watchLog">
{{ item }}
</li>
</ul> 
 
 
<h2>
$watch( collection, [ Equality = true ] ) Log
</h2>
equality = true, or deep watch checks also if any property inside
the collection has changed, i.e it will trigger if an element
is added, or if an element has a changed value. This can become
very expensive.
 
<ul>
<li ng-repeat="item in watchEqualityLog">
{{ item }}
</li>
</ul>
 
<h2>
$watchCollection( collection ) Log
</h2>
watchCollection shallow watches the content of an collection.
It is only triggered if an element is added, removed or moved.
 
<ul>
<li ng-repeat="item in watchCollectionLog">
{{ item }}
</li>
</ul>

 
  </body>

</html>
// Code goes here

	// Create an application module for our demo.
var app = angular.module( "Demo", [] );
 
 
// -------------------------------------------------- //
// -------------------------------------------------- //
 
 
// I control the root of the application.
app.controller(
"AppController",
function( $scope ) {
 
// These are the log item to render upon change.
$scope.watchCollectionLog = [];
$scope.watchLog = [];
$scope.watchEqualityLog = [];
 
// I am the collection being watched.
$scope.collection = [
{
id: 1,
value: 0
}
];
 
 
// Use the relatively new watchCollection().
$scope.$watchCollection(
"collection",
function( newValue, oldValue ) {
 
addLogItem( $scope.watchCollectionLog );
 
}
);
 
// Use the old watch() with default object equality,
// which defaults to use object REFERENCE checks.
$scope.$watch(
"collection",
function( newValue, oldValue ) {
 
addLogItem( $scope.watchLog );
 
}
);
 
// Use the old watch() method, but turn on deep object
// equality, which will compare the deep object tree
// for changes.
$scope.$watch(
"collection",
function( newValue, oldValue ) {
 
addLogItem( $scope.watchEqualityLog );
 
},
true // Object equality (not just reference).
);
 
 
// ---
// PUBLIC METHODS.
// ---
 
 
// Change a deep value in an existing item on in the
// current collection.
$scope.changeDeepValue = function() {


$scope.collection[ 0 ].value = now();
 
};
 
 
// Add a new item to the collection, causing a change
// in the shallow topology of the collection.
$scope.changeShallowValue = function() {
 
// Add new item to collection.
$scope.collection.push({
id: ( $scope.collection.length + 1 ),
value: now()
});
 
};

$scope.empty = function() {
  $scope.collection.length = 0;
} 
 
 
// I clear the log items.
$scope.clear = function() {
  $scope.watchCollectionLog = [];
  $scope.watchLog = [];
  $scope.watchEqualityLog = [];
};
 
 
// I rebuild the underlying collection, completely
// changing the reference.
$scope.rebuild = function() {
 
$scope.collection = [{
id: 1,
value: 0
}];
 
};
 
 
// ---
// PRIVATE METHODS.
// ---
 
 
// I add a log item to the beginning of the given log.
function addLogItem( log ) {
 
var logItem = (
"Executed: " + now() +
" ( length: " + $scope.collection.length + " )"
);
 
log.splice( 0, 0, logItem );
 
}
 
 
// I return the current UTC milliseconds.
function now() {
 
return( ( new Date() ).getTime() );
 
}
 
}
);
 
/* Styles go here */