Works by

Ren's blog

@rennnosuke_rk 技術ブログです

【AngularJS】データモデルの変更を監視する$watch

$watchとは

AngularJS(以下Angular)では、ビューとロジック間で一つのモデルを共有することができます。 モデルの変更をビューに動的に反映でき、逆にビューの変更をモデルに反映させることができます。

例えば、HTML上のプルダウンにng-modelでモデル名を指定すると、
対応するAngularのController内で指定したモデル名経由でプルダウンの値を参照することができます。

<!-- モデルをビューのタグに紐付け -->
<select ng-model="menu_item" ng-options="m for m in menu"></select>
/*
 * Controller
 */

// メニュー
$scope.menu = ["apple", "banana", "orange"];
// デフォルトのメニュー選択
$scope.menu_item = $scope.menu[0];

逆に、Controller側からモデルに対して操作を行うと、その結果がビューに反映されます。
上の例では、Controller上でモデルに値を設定しています。これにより、プルダウンで表示する値を設定できます。

このように、Angular上ではビュー・ロジック間でモデルを共有し、モデルを軸にフロントを構築していきます。

ただAngularではモデルだけでなく、特定のオブジェクトの変化も監視したい時があります。
そのようなときに使用できるのが$scope.$watch()です。

$watch

オブジェクトの変更を監視する

$scope.$watch()は、第一引数に監視したいオブジェクトを返す関数を指定し、第二引数にモデル変更時の処理を記述した関数を渡すことで使用できます。
オブジェクトの参照が変更された場合に、第二引数の処理が走ります。

$scope.$watch(function(){
        return $scope.menu_item;
    }, function(newValue, oldValue, scope){
        // menu_item変更時に走る処理
        console.log(newValue);
    });

$scope内モデルの変更を監視する

第一引数の関数が返すオブジェクトが$scopeが管理するモデルの場合、名前を指定するだけで同様の効果を得られます。

 
$scope.$watch('menu_item', function(newValue, oldValue, scope){
    // menu_item変更時に走る処理
    console.log(newValue);
});

プロパティの変化を監視する

注意したいのは、デフォルトの$watchは参照の変化のみをトレースすることです。
プロパティ値の変化まで監視する場合には、第三引数にtrueを指定します。

$scope.$watch(function(){
        return $scope.menu_item;
    }, function(newValue, oldValue, scope){
        // menu_item変更時に走る処理
        console.log(newValue);
    }, true);

複数の監視対象を指定する

$watchGroupを使用することで、複数の監視対象を設定することができます。
ただし、$watchGroupにはプロパティ値変化監視オプションがありません。

$scope.$watchGroup(["menu_item", "menu"], function(newValue, orldValue, scope) {
        // menu_item,menu変更時に走る処理
        console.log(newValue);
});