UPDATE
offerte angolari adesso i due metodi di ambito $watchGroup (dal 1,3) e $watchCollection. Quelli sono stati menzionati da @blazemonger e @kargold.
Questo dovrebbe funzionare indipendentemente dalle tipologie e valori:
$scope.$watch('[age,name]', function() { ... }, true);
è necessario impostare il terzo parametro di vero in questo caso.
La concatenazione di stringhe 'age + name'
fallirà in un caso come questo:
<button ng-init="age=42;name='foo'" ng-click="age=4;name='2foo'">click</button>
Prima che l'utente fa clic sul pulsante il valore osservato sarebbe 42foo
(42
+ foo
) e dopo il clic 42foo
(4
+ 2foo
) . Quindi la funzione orologio non verrebbe chiamata. Quindi meglio usare un'espressione di array se non puoi garantire che tale caso non apparirà.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link href="//cdn.jsdelivr.net/jasmine/1.3.1/jasmine.css" rel="stylesheet" />
<script src="//cdn.jsdelivr.net/jasmine/1.3.1/jasmine.js"></script>
<script src="//cdn.jsdelivr.net/jasmine/1.3.1/jasmine-html.js"></script>
<script src="http://code.angularjs.org/1.2.0-rc.2/angular.js"></script>
<script src="http://code.angularjs.org/1.2.0-rc.2/angular-mocks.js"></script>
<script>
angular.module('demo', []).controller('MainCtrl', function ($scope) {
$scope.firstWatchFunctionCounter = 0;
$scope.secondWatchFunctionCounter = 0;
$scope.$watch('[age, name]', function() { $scope.firstWatchFunctionCounter++; }, true);
$scope.$watch('age + name', function() { $scope.secondWatchFunctionCounter++; });
});
describe('Demo module', function() {
beforeEach(module('demo'));
describe('MainCtrl', function() {
it('watch function should increment a counter', inject(function ($controller, $rootScope) {
var scope = $rootScope.$new();
scope.age = 42;
scope.name = 'foo';
var ctrl = $controller('MainCtrl', { '$scope': scope });
scope.$digest();
expect(scope.firstWatchFunctionCounter).toBe(1);
expect(scope.secondWatchFunctionCounter).toBe(1);
scope.age = 4;
scope.name = '2foo';
scope.$digest();
expect(scope.firstWatchFunctionCounter).toBe(2);
expect(scope.secondWatchFunctionCounter).toBe(2); // This will fail!
}));
});
});
(function() {
var jasmineEnv = jasmine.getEnv();
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.specFilter = function (spec) {
return htmlReporter.specFilter(spec);
};
var currentWindowOnload = window.onload;
window.onload = function() {
if (currentWindowOnload) {
currentWindowOnload();
}
execJasmine();
};
function execJasmine() {
jasmineEnv.execute();
}
})();
</script>
</head>
<body></body>
</html>
http://plnkr.co/edit/2DwCOftQTltWFbEDiDlA?p=preview
PS:
Come indicato da @reblace in un commento, è naturalmente possibile accedere ai valori:
$scope.$watch('[age,name]', function (newValue, oldValue) {
var newAge = newValue[0];
var newName = newValue[1];
var oldAge = oldValue[0];
var oldName = oldValue[1];
}, true);
C'è [un post di blog molto buono da Ben Nadel] (http://www.bennadel.com/blog/2566-Scope-watch-vs-watchCollection-In-AngularJS.htm) sull'argomento di $ watch vs $ watchCollection che potresti trovare utile. –