Friday, 29 May 2015

AngularJS $watch() vs $watchCollection()

Live demo
<!doctype html>
<html ng-app="Demo">
<head>
<title>Scope $watch() vs. $watchCollection() In AngularJS </title>
</head>
<style type="text/css">
a[ ng-click ] {
cursor: pointer;
text-decoration: underline;
}
</style>
<body ng-controller="AppController">
<h2>Scope $watch() vs. $watchCollection() In AngularJS</h2>
<h3>The collection:</h3>
<ul>
<li ng-repeat="item in collection">
id: {{ item.id }} timestamp: {{ item.value }}
</li>
</ul>
<p>
<a ng-click="changeShallowValue()">Add item to collection (shallow change)</a>
&mdash;
<a ng-click="changeDeepValue()">Change property on item (deep change)</a>
&mdash;
<a ng-click="rebuild()">Rebuild collection</a>
&mdash;
<a ng-click="clear()">Clear logs</a>
</p>
<h3>$watchCollection( collection ) Log</h3>
<ul>
<li ng-repeat="item in watchCollectionLog">{{ item }}</li>
</ul>
<h3>$watch( collection ) Log</h3>
<ul>
<li ng-repeat="item in watchLog">{{ item }}</li>
</ul>
<h3>$watch( collection, [ Equality = true ] ) Log</h3>
<ul>
<li ng-repeat="item in watchEqualityLog">{{ item }}</li>
</ul>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.0-rc.1/angular.min.js"></script>
<script type="text/javascript">
// Create an application module for our demo.
var app = angular.module("Demo", []);
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 watchCollection().
$scope.$watchCollection(
"collection",
function (newValue, oldValue) {
addLogItem($scope.watchCollectionLog);
}
);
// Use watch() with default object equality,
// which defaults to use object REFERENCE checks.
$scope.$watch(
"collection",
function (newValue, oldValue) {
addLogItem($scope.watchLog);
}
);
// Use 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).
);
// Change a deep value in an existing item on in the
// current collection.
$scope.changeDeepValue = function () {
// Add new item to collection.
$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()
});
};
// 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
}];
};
// 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()).toUTCString());
}
}
);
</script>
</body>
</html>
view raw angular-watch hosted with ❤ by GitHub

Here is a comparison of the watch and watchCollection (default by ref) and watchCollection (by val equality). This code was based on a post from Ben Nadel's blog.


No comments:

Post a Comment