Ionicを勉強する機会があったので、基礎学習として元になっているAngularJSについても勉強してみました。
色々探してみて、最終的に公式サイトのメニューからたどり着いたのがCode Schoolのチュートリアルです。
Code Schoolを利用したのは今回が初めてでしたが、動画レクチャーとハンズオンを交互に行うスタイルはインプットとアウトプットのイテレーションを素早く回せてよいですね。
また、授業の内容も上手に組み立てられていたように思います。一歩ずつ丁寧に説明してくれるので、頭の中にブラックボックスを作らずに理解を積み重ねていくことができました。特にありがたかった点は、一度たりとも$scope
が登場しなかったところです。
$scopeは使わなければならないのか?
AngularJS関連の記事を見ていると、とにかくそこら中に$scope
が出てきます。なんだこれはおまじないかと思うくらいに出てきます。
本当におまじないならひとまず無視して先に進めるのもアリなのですが、こいつの場合はコントローラとテンプレートの間のデータや挙動を共有するのに使われるので頭から追い出すわけにもいかず、初心者からすると魔法の箱にしか見えない感じの理解に落ち着いてしまいます。
グローバル変数への憎しみを持つ人間としては、得体の知れない同じ名前の場所に複数のコントローラから値を突っ込んでテンプレート側で取り出すなんて操作を行うのを強要されるのは、正直苦痛なのです。
ちょっと前までは、僕の中でのAngularJSのイメージは下記のような感じでした。
// app.js angular.module('gemStore', []) .controller('StoreController', function($scope) { $scope.product = { name: 'Azurite', price: 2.95 }; });
<!-- index.html --> <body ng-controller="StoreController"> <div class="product row"> <h3> {{product.name}} <em class="pull-right">{{product.price}}</em> </h3> </div> </body>
そのproduct
はどこから出てきたんだよ・・・・!!!!という感じですね。魔法っぽさMAXです。
しかし、Shaping up with Angular.jsでは下記のような形でチュートリアルを進めていくのです。
// app.js angular.module('gemStore', []) .controller('StoreController', function() { this.product = { name: 'Azurite', price: 2.95 }; });
<!-- index.html --> <body ng-controller="StoreController as store"> <div class="product row"> <h3> {{store.product.name}} <em class="pull-right">{{store.product.price}}</em> </h3> </div> </body>
あ、product
はStoreController
に入っていたものを別名のstore
を通じて取り出したんだね。コントローラ側のthis
とテンプレート側のstore
が同じものなんだね。わかりやすいね!
この"Controller As"と呼ばれる記法は、AngularJS 1.2で追加されたものだそうです。
えっ、$scope
要らんやん。なんでみんな$scope
使うん?
と思ってググったりリプもらったりした結果、やっぱり$scope
を使うべき場所というのはかなり減ってきている印象を受けました。
@Nkzn $scopeよりcontrollerAsをメインで使おうな!
— わかめ@TypeScriptカッコガチ (@vvakame) 2015, 9月 25
近い未来に現れるであろうAngular 2では$scope
は無くなるとのことですし、$scope
を使うやり方には慣れ親しまないほうがよさそうです。*1
バッドプラクティスを身につけずに済んだよ! ありがとうCode School! ありがとうGregg!
余談: IonicでハマったAngularJSの話
その後、Ionicの練習を始めてハマった点を紹介します。
その1: controllerしか指定できないところでController Asを使いたい
$ ionic start myApp tabs
上記のコマンドでIonicプロジェクトを作成すると、app.js内に下記のようなコードが生成されます。
$stateProvider ... .state('tab.account', { url: '/account', views: { 'tab-account': { templateUrl: 'templates/tab-account.html', controller: 'AccountCtrl' // controllerAs: 'account' <= これは指定できない???? } } })
Code Schoolのチュートリアルでは、controller
を指定した直後にcontrollerAs
を指定する感じで中盤以降の話題が進んでいきます。
しかしリファレンスを見ると、残念ながらviews
オブジェクトにはcontrollerAs
がありません。
これにはだいぶ悩まされましたが、最終的には下記の形でOKでした。
$stateProvider ... .state('tab.account', { url: '/account', views: { 'tab-account': { templateUrl: 'templates/tab-account.html', controller: 'AccountCtrl as account' } } })
ng-controller
で似たようなことやってましたね。初心に帰れ的なやつでした。。。
その2: $IonicModalを使うと$scopeから逃げきれない
上記の公式チュートリアルではTodoアプリを作っていくのですが、タスクの作成にモーダルを用いています。こいつがちょっと厄介です。
$IonicModal
のリファレンスから、サンプルコードを一部抜粋します。
$ionicModal.fromTemplateUrl('my-modal.html', { scope: $scope, // <= 置き換え不可能 animation: 'slide-in-up' }).then(function(modal) { $scope.modal = modal; // <= Controller Asを利用すれば$scopeをthisに置き換え可能 });
$scope
の利用を強要してくるAPIつらいな・・・?
どうにかしてthis
方面の何かに置き換えられないかと色々調べてみたのですが、StackOverflowで見つけた一番信憑性ありそうな回答がこれ↓でした。
In order to access the $new() function that AngularJs provides to create child scopes, you need to provide an AngularJs
$scope
object
内部で$scope
をちゃんと使っちゃってるっぽいです。大人しく$scope
を使うか、そもそも$IonicModal
を使わない設計にするかでしか解決できなさそうな問題でした。
まとめ
- Code SchoolのShaping up with Angular.jsめっちゃよかった
$scope
は基本的に使わないほうがよさそう- IonicのAPIとかSampleがAngularJS初心者につらいときある
AngularJSとIonicの基本操作は分かってきたので、そろそろTypeScriptでやりたい気持ちが高まってきてます。
簡単なアプリ作って、モバイルアプリのプロトタイピング力を高めていきたいです。まる。

Full Stack Mobile App with Ionic Framework (English Edition)
- 作者: Hoc Phan
- 出版社/メーカー: Hoc Phan
- 発売日: 2014/11/30
- メディア: Kindle版
- この商品を含むブログを見る
*1:$scopeを使わないとできないこともあるみたいなので、完全に使わないわけにもいかないでしょうけれども。