$scope.$watch
Angular で複数の変数を作成し、そのうちの 1 つが変更されたときにコールバックをトリガーする方法。
$scope.name = ...
$scope.age = ...
$scope.$watch('???',function(){
//called when name or age changed
})
$scope.$watch
Angular で複数の変数を作成し、そのうちの 1 つが変更されたときにコールバックをトリガーする方法。
$scope.name = ...
$scope.age = ...
$scope.$watch('???',function(){
//called when name or age changed
})
アップデート
Angular は$watchGroup (1.3 以降) と$watchCollectionの 2 つのスコープ メソッドを提供するようになりました。これらは @blazemonger と @kargold によって言及されています。
これは、型と値に関係なく機能するはずです。
$scope.$watch('[age,name]', function () { ... }, true);
この場合、3 番目のパラメーターを true に設定する必要があります。
次のような場合、文字列の連結'age + name'
は失敗します。
<button ng-init="age=42;name='foo'" ng-click="age=4;name='2foo'">click</button>
ユーザーがボタンをクリックする前は、監視値は42foo
( 42
+ foo
) になり、クリック後は42foo
( 4
+ 2foo
) になります。したがって、watch 関数は呼び出されません。そのため、そのようなケースが発生しないことを確認できない場合は、配列式を使用することをお勧めします。
<!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:
コメントで @reblace が述べているように、値にアクセスすることはもちろん可能です。
$scope.$watch('[age,name]', function (newValue, oldValue) {
var newAge = newValue[0];
var newName = newValue[1];
var oldAge = oldValue[0];
var oldName = oldValue[1];
}, true);
$scope.$watch('age + name', function () {
//called when name or age changed
});
Angular 1.3 は、特にこの目的のために $watchGroup を提供します。
https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watchGroup
これは、式の配列に対する標準の $watch と同じ最終結果を提供するようです。コードの意図が明確になるので気に入っています。
誰も明白なことに言及していません:
var myCallback = function() { console.log("name or age changed"); };
$scope.$watch("name", myCallback);
$scope.$watch("age", myCallback);
これは、ポーリングが少し少ないことを意味する場合があります。name + age
(この場合) と(他の場所) の両方を監視する場合、name
Angular は事実上name
2 回見て、それが汚れているかどうかを確認すると思います。
コールバックをインライン化するのではなく、名前で使用する方が間違いなく読みやすいです。特に、私の例よりも良い名前を付けることができれば.
また、必要に応じて、さまざまな方法で値を監視できます。
$scope.$watch("buyers", myCallback, true);
$scope.$watchCollection("sellers", myCallback);
$watchGroup
使用できればいいのですが、私が知る限り、グループ メンバーをコレクションとして、またはオブジェクトの等価性で監視することはできません。
1 つの同じコールバック関数呼び出し内で両方の式の古い値と新しい値が必要な場合は、おそらく他の提案されたソリューションのいくつかがより便利です。