2013年07月02日

AngularJSを使って画面遷移、バリデーションなど。

今回はJS用MVCフレームワークのAngularJSを使ってデータの受け渡しの伴う画面遷移やバリデーション処理をやってみたいと思う。
ここで作ったTODOアプリを改造する。今まで一つの画面だけで完結していたTODOアプリをあえてデータ受け渡しの伴う画面遷移があるアプリに作り変えてみる。
画面は二つ、TODO一覧画面とTODO入力画面だ。

まずはプロジェクト構成から。Chrome Packaged Appsなアプリのための構成になっている。

manifest.json
angular.min.js
background.js
app.js
index.html
list.html
detail.html
todo.css
calculator-128.png
calculator-64.png

今回重要なのは太字の箇所。それ以外は前回と同じ。

まずはindex.htmlから見てみよう。
<html ng-app="todo" ng-csp>
  <head>
    <script src="angular.min.js"></script>
    <script src="app.js"></script>
    <link rel="stylesheet" href="todo.css">
  </head>
  <body>
    <h2>Todo</h2>
    <div ng-view></div>
  </body>
</html>

ng-app="todo" でアプリ名を指定。
app.js にはコントローラーが記述されている。
画面遷移すると ng-view の部分が切り替わる。

次は一覧画面 list.html
<span>{{remaining()}} of {{todos.length}} remaining</span>
[ <a href="" ng-click="archive()">archive</a> ]
<br/>
<input type="text" ng-model="search" class="search-query" placeholder="Search">
<table>
 <thead>
  <tr>
   <th>Todo</th>
   <th><a href="#/new">(New)</a></th>
  </tr>
 </thead>
 <tbody>
  <tr ng-repeat="todo in todos | filter:search | orderBy:'text'">
   <td>
     <input type="checkbox" ng-model="todo.done">
     <span class="done-{{todo.done}}">{{todo.text}}</span>
   </td>
   <td></td>
 </tr>
 </tbody>
</table>

基本的には前回のTODOアプリと変わらないのだが、今回は、
<input type="text" ng-model="search" class="search-query" placeholder="Search">

<tr ng-repeat="todo in todos | filter:search | orderBy:'text'">
でフィルタとソートが実装されていたり、
入力画面へ飛ぶためのリンク
<th><a href="#/new">(New)</a></th>
があったりする。

次に入力画面 detail.html
<form name="myForm">
 <div class="control-group" ng-class="{error: myForm.todoText.$invalid}">
  <label>TODO</label>
  <input type="text" name="todoText" ng-model="todoText" placeholder="add new todo here" size="30" required>
  <span ng-show="myForm.todoText.$error.required" class="help-inline">Required</span>
 </div>
 <br>
 <a href="#/" class="btn btn-cancel">Cancel</a>
 <button ng-click="addTodo()" ng-disabled="myForm.$invalid" class="btn btn-primary">Add</button>
</form>

<form name="myForm">
でフォーム名"myForm"を定義し、
<div class="control-group" ng-class="{error: myForm.todoText.$invalid}">
<input type="text" name="todoText" ng-model="todoText" placeholder="add new todo here" size="30" required>
<span ng-show="myForm.todoText.$error.required" class="help-inline">Required</span>
</div>
でテキストボックスに“入力必須”のバリデーション required を組み込んでいる。
まー特に説明の必要もないだろう。

では最後に最も重要なコントローラーの実装を見てみよう。
app.js
angular.module('todo', []).
  config(function($routeProvider) {
    $routeProvider.
      when('/', {controller:ListCtrl, templateUrl:'list.html'}).
      when('/new', {controller:CreateCtrl, templateUrl:'detail.html'}).
      otherwise({redirectTo:'/'});
  });
    
function ListCtrl($scope, $rootScope) {
  
  $scope.remaining = function() {
    var count = 0;
    angular.forEach($rootScope.todos, function(todo) {
      count += todo.done ? 0 : 1;
    });
    return count;
  };

  $scope.archive = function() {
    var oldTodos = $rootScope.todos;
    $rootScope.todos = [];
    angular.forEach(oldTodos, function(todo) {
      if (!todo.done) $rootScope.todos.push(todo);
    });
  };
}
    
function CreateCtrl($scope, $rootScope, $location) {
  $rootScope.addTodo = function() {
    if(!$rootScope.todos){
      $rootScope.todos = [];
    }
    $rootScope.todos.push({text:$scope.todoText, done:false});
    $location.path('/');
  };
}

1行目でアプリ名"todo"を指定し、2行目からrouteProviderを設定している。そこでは、URIとそれに紐づくコントローラーや画面テンプレートを定義している。
"/" が呼ばれたら "ListCtrl" が実行されて、 "list.html" が描画される、、、みたいな感じ。

そこから下はコントローラーの実装。今回はListCtrl(一覧画面用)とCreateCtrl(入力画面用)の二つだけ。
前回のTODOアプリと違うのは、TODO一覧の値 "todos" を $scope ではなく $rootScope で参照していること。こうすることで画面を跨いだ todos の受け渡しが可能となる。
CreateCtrlの最後の $location.path('/'); という行は入力画面コントローラー処理から抜けるために飛び先 "/" を指定している。

さらりと説明したが、今回最も大切なのは app.js の中の routeProvider の設定と $rootScope である。自分は$rootScopeの存在を知らずに少しハマってました。


参考
NEXTCODE BLOG: AngularJSでController間の通信を行う
Angular.jsについてちょっとしゃべる - slideshare


関連エントリ
JS用MVCフレームワーク「AngularJS」を使ってChrome Packaged Apps【基本編】
【Chrome】Packaged Apps アプリをHelloWorld【Google】
スマホOSの主導権争いの行方
posted by 寄り道退屈男 at 15:19 | Comment(0) | TrackBack(0) | Packaged Apps
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス: [必須入力]

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/70337723
※言及リンクのないトラックバックは受信されません。

この記事へのトラックバック