チュートリアル:WindowsストアアプリをAngularJSで作ってみる(Part 2)

Windows Store Tutorial Part 2

AngularJSを使ってWindowsストアアプリを作ってみる

このチュートリアルは、AngularJSを使ってWindowsストアアプリを使って作ってみます。

Part 1では、HelloWorld!を、Microsoft独自のJavaScriptのライブラリを実装したWinJSだけで作ってみました。

Part 2では、同じアプリをAngularJSで作ってみます。


チュートリアル(Part 2)

Part 1のチュートリアルでは、Microsoftが出している HelloWorld!の事例をもとに、Microsoftが提供するWindowsストア用のJavaScriptライブラリ、WinJSだけでアプリだけで作ってみました。見かけはAngularJSっぽい動きにしましたが、ソースコードはAngularJS抜きで実現しました。

こんどは、早速、AngularJSで同じWindowsストアアプリに挑戦してみます。


最初のAngularJS+Windowsストアアプリ:「ハローワールド!」

MicrosoftのHelloWorld!の事例は、ユーザーが名前をInputフィールドに入れてボタンをクリックすると、Inputフィールドの下に「Hello ○○!」と表示されるものです。

そこの部分をAngularJSに置き換えて、Inputフィールドに何かを入力するたびに、Inputフィールドの下に入力した文字列を表示するようにしました。

完成したAngularJSでのHelloWorld!は次のような感じです:


default.htmlの中身

default.htmlは、Part 1と比べて、3点ほど違いがありますが、ここでは default.html のソースコードをご覧になってください。

default.htmlのソースコードは次ぎのとおりです:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta charset="utf-8" />
<title>HelloWorldInAngularJS.Windows</title>

<!-- WinJS 参照 -->
<link href="//Microsoft.WinJS.2.0/css/ui-light.css" rel="stylesheet" />
<script src="//Microsoft.WinJS.2.0/js/base.js"></script>
<script src="//Microsoft.WinJS.2.0/js/ui.js"></script>

<!-- HelloWorldInAngularJS.Windows 参照 -->
<link href="/css/default.css" rel="stylesheet" />
<script src="/js/default.js"></script>

<!-- AngularJS 参照 -->
<script src="/js/angular.js"></script>


</head>
<body>
    <h1 class="headerClass">Hello AngularJS!</h1>
    <h1 class="headerClass">Hello Windows Store!</h1>
    
    <div ng-app="" class="mainContent">
        <p>お名前はなんですか?</p>
        <input id="nameInput" type="text" ng-model="name" ng-init=" name = 'you'" />
        <!-- 
            <button id="helloButton">「こんにちは」と言って!</button>
            <div id="greetingOutput"></div>
        -->
        <p>Hello, {{name}} !</p>
        <br />
        <label for="ratingControlDiv">
            この挨拶を評価してください:
        </label>
        <div id="ratingControlDiv" data-win-control="WinJS.UI.Rating">
        </div>
        <div id="ratingOutput"></div>
    </div>

</body>
</html>

default.htmlの違い:その1

AngularJSのライブラリを /js/ のディレクトリにコピーして、default.htmlの中で参照しました。

VisualStudioの**/js/**フォルダ:

AngularJS Library in VisualStudio

    <!-- AngularJS 参照 -->
    <script src="/js/angular.js"></script>   

理由は後でのべますが、ここでは、minified(圧縮)バージョンでは無く、圧縮されていないバージョンのライブラリをダウンロードしてください。


default.htmlの違い:その2

ダウンロードしたAngularJSのライブラリ(angular.js)を、そのまま使うと、VisualStudioでランタイムエラーが出ます。

このエラーは、「ダイナミック・コンテンツを追加できない(エラーコード:0x800c001c)」という内容です。エラーの理由は、AngularJSではダイナミックなコンテンツを扱う機能がありますが、Microsoftは、セキュリティを強化するために、信頼しないデータソース(この場合はAngularJS)には、それを許しません。

このエラーを回避するために、先ほどのangular.jsのソースコードをエディターで開いて、次ぎの2カ所修正します(これがminifiedバージョンを使わない理由です)。

修正箇所1:

修正前

append: function(element, node) {
forEach(new JQLite(node), function(child){
  if (element.nodeType === 1 || element.nodeType === 11) {
    element.appendChild(child);
  }
});
},

修正後

append: function (element, node) {
  MSApp.execUnsafeLocalFunction(function(){
      forEach(new JQLite(node), function (child) {
          if (element.nodeType === 1 || element.nodeType === 11) {
              element.appendChild(child);
          }
      });
  });
},

修正箇所2:

修正前

prepend: function(element, node) {
if (element.nodeType === 1) {
  var index = element.firstChild;
  forEach(new JQLite(node), function(child){
    element.insertBefore(child, index);
  });
}
},

修正後

prepend: function (element, node) {
  MSApp.execUnsafeLocalFunction(function () {
      if (element.nodeType === 1) {
          var index = element.firstChild;
          forEach(new JQLite(node), function (child) {
              element.insertBefore(child, index);
          });
      }
  });
},

このように、「危ない」と判断されるコードを、MSApp.execUnsafeLocalFunction()で囲むことにより、ランタイムエラーは出なくなります。


default.htmlの違い:その3

ソースコードの中に、AngularJSの構文を入れました(ng-app, ng-model, ng-init, {{name}})。ここではボタンは必要ないので、コメントにしました。

<div ng-app="" class="mainContent">
        <p>お名前はなんですか?</p>
        <input id="nameInput" type="text" ng-model="name" ng-init=" name = 'you'" />
        <!-- 
            <button id="helloButton">「こんにちは」と言って!</button>
            <div id="greetingOutput"></div>
        -->
        <p>Hello, {{name}} !</p>
        <br />
        <label for="ratingControlDiv">
            この挨拶を評価してください:
        </label>
        <div id="ratingControlDiv" data-win-control="WinJS.UI.Rating">
        </div>
        <div id="ratingOutput"></div>
</div>

これで完成です。

参考:このAngularJSの部分は、前のブログの記事のJSFiddleを使ったハローワールド!の事例と似ていますので、ご覧ください。


default.jsの中身

default.jsは、Part 1とほぼかわりません。違うところは、ボタンとinputフィールドにイベントハンドラーを登録するところと、イベントハンドラーの関数そのものが必要なくなります。

default.jsのソースコードは次のとおりです:

(function () {
"use strict";

var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;

app.onactivated = function (args) {
    if (args.detail.kind === activation.ActivationKind.launch) {
        if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
            // TODO: このアプリケーションは新しく起動しました。ここでアプリケーションを
            // 初期化します。
        } else {
            // TODO: このアプリケーションは中断状態から再度アクティブ化されました。
            // ここでアプリケーションの状態を復元します。
        }
        args.setPromise(WinJS.UI.processAll().then(function completed() {

            // レーティングコントロールのDIVタグのエレメントを参照する
            var ratingControlDiv = document.getElementById("ratingControlDiv");

            // レーティングコントロールそのものを参照する
            var ratingControl = ratingControlDiv.winControl;

            // レーティングコントロール用のイベントハンドラーを登録する
            ratingControl.addEventListener("change", ratingChanged, false);

        }));
    }
};

app.oncheckpoint = function (args) {
    // TODO: このアプリケーションは中断しようとしています。ここで中断中に
    // 維持する必要のある状態を保存します。中断中に自動的に保存され、
    // 復元される WinJS.Application.sessionState オブジェクトを使用
    // できます。アプリケーションを中断する前に
    // 非同期操作を完了する必要がある場合は、
    // args.setPromise() を呼び出してください。
};

function ratingChanged(eventInfo) {

    var ratingOutput = document.getElementById("ratingOutput");
    ratingOutput.innerText = eventInfo.detail.tentativeRating;
}

app.start();
})();

default.cssの中身

default.cssは、Part 1と全くかわりありません。


Windowsストアアプリ+AngularJSをもっと相性良くする

これで、AngularJSを使ってWindowsストアアプリが作れましたね。ただ、AngularJSWinJSとの相性をよくするためには、さらに努力が必要になります。

それについて次回サンプルを作りますね。
では、ばりばりAngularJSで、Windowsストアアプリ作ってください!

Mahalo!