かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

TypeScriptとAngularJS「プロパティの監視とコレクションのバインド」

とあるプロパティの値の変化を監視して、その中身をコレクションに履歴として収集するようにするアプリを組んでみました。ここまで、すんなりいってるので怖いです。

TypeScript側

ポイントは$scopeの$watch関数。こいつに監視したいスコープのプロパティを文字列で指定することで、コールバックを登録できます。コールバックには新しい値と古い値とスコープがわたってきます。今回は最後のスコープはいらない子だったので、特に受け取っていません。

受け取った値は、コレクションに収集しています。

/// <reference path="scripts/typings/angularjs/angular.d.ts" />

module MyApp {
    // scopeに持たせるオブジェクト
    class MessageHolder {
        message = "";
        messageLog = new Array<string>();
    }

    // 
    interface MessageScope extends ng.IScope {
        messageHolder: MessageHolder;

        greet(): void;
    }

    class MessageCtrl {
        constructor(private $scope: MessageScope) {
            $scope.messageHolder = new MessageHolder();

            $scope.greet = () => {
                $scope.messageHolder.message = "Hello at " + Date(); 
            };
            // $watchで指定したプロパティを監視するコールバックを登録できる
            $scope.$watch("messageHolder.message", (newVal, oldVal) => {
                // 新しい値が無効な場合は何もしない
                if (!newVal) {
                    return;
                }

                // 古い値 -> 新しい値の形式でログをとる
                $scope.messageHolder.messageLog.push(oldVal + " -> " + newVal);
            });
        }
    }

    angular.module("myApp", [])
        .controller("MessageCtrl", ["$scope", MessageCtrl]);
}

HTML側

HTML側では、最後のほうでng-repeatを使いコレクションの要素を1つ1つテンプレートで展開しています。ここではli要素にしてるだけですね。なので結果は単純なリスト表示になります。

<!DOCTYPE html>

<html lang="ja" ng-app="myApp">
<head>
    <meta charset="utf-8" />
    <title>TypeScript HTML App</title>
    <link rel="stylesheet" href="app.css" type="text/css" />
    <script src="Scripts/angular.min.js"></script>
    <script src="app.js"></script>
</head>
<body>
    <h1>TypeScript HTML App</h1>

    <div id="content" ng-controller="MessageCtrl">
        <span>{{messageHolder.message}}</span>
        <hr />
        <input type="button" ng-click="greet()" value="greet" />

        <hr />
        <ul>
            <!-- ng-repeatを使ってコレクションの数だけテンプレートを展開できる -->
            <li ng-repeat="m in messageHolder.messageLog">{{m}}</li>
        </ul>
    </div>
</body>
</html>

実行結果

実行して、何回かボタンを押すと以下のようになります。ちゃんと動いてるっぽい。

f:id:okazuki:20140526082003p:plain