OnsenUI+AngularJS1.5でコンポーネント化する際の注意点

※記事の内容は相当古いです。AngularJSではなく、Angularを使いましょう。

# 記事の対象者
- OnsenUIを使っている人
- AngularJS1.5のComponentを使いたい人

# 問題
新しいものが好きだ。

Angular2への移行を見越してComponentベースで実装してみたはいいが、
・ ons-sliding-menu とか
・ ons-pull-hook
がうまく動かない。

具体的には、templateUrlで指定した「***.html」内の
・ menu.toggleMenu()が動かない
・ loader.getCurrentState()が動かない

# 解決策
コンポーネントのテンプレートではvarを直接参照できないので、$ctrlからアクセスするように変更する。

# 方法
例えばこんな感じにページを作ったとする。
スライドメニューがあって、何かの一覧表示のためのコンポーネントが入っている。

```html:www/pages/group-list.html

<!-- グループ一覧ページ -->
<ons-sliding-menu var="menu" main-page="page.html" menu-page="menu.html" swipe-target-width="100px" max-slide-distance="200px" type="reveal" side="left">
</ons-sliding-menu>

<!-- ページ本体 -->
<ons-template id="page.html">
    <group-list title="グループ一覧"></group-list>
</ons-template>

<!-- メニュー -->
<ons-template id="menu.html">
    <ons-page>
        <ons-list>
            <ons-list-item modifier="tappable chevron">
                設定
            </ons-list-item>
            <ons-list-item modifier="tappable chevron" ng-click="nav.popPage()">
                ログアウト
            </ons-list-item>
        </ons-list>
    </ons-page>
</ons-template>
```

そしてgroup-listコンポーネントのテンプレートはこちら。

```html:www/template/group-list.html
<ons-page>
    <ons-pull-hook ng-action="$ctrl.load($done)" var="loader" threshold-height="-1px">
        <span ng-switch="$ctrl.loader.getCurrentState()">
            <span ng-switch-when="initial"><ons-icon size="35px" icon="ion-arrow-down-a"></ons-icon> Pull down to refresh</span>
            <span ng-switch-when="preaction"><ons-icon size="35px" icon="ion-arrow-up-a"></ons-icon> Release to refresh</span>
            <span ng-switch-when="action"><ons-icon size="35px" spin="true" icon="ion-load-d"></ons-icon> Loading data...</span>
        </span>
    </ons-pull-hook>
    
    <ons-toolbar>
        <div class="left">
            <ons-toolbar-button ng-click="$ctrl.menu.toggleMenu()">
                <ons-icon icon="ion-navicon" size="28px" fixed-width="false"></ons-icon>
            </ons-toolbar-button>
        </div>
        <div class="center">{{$ctrl.title}}</div>
    </ons-toolbar>

    <ons-list>
        <ons-list-item class="list-item-container" modifier="tappable chevron" ng-repeat="group in $ctrl.groupList">{{group.Grpname}}</ons-list-item>
    </ons-list>
    
</ons-page>
```

見ての通り、元の
`ng-switch="loader.getCurrentState()"` `ng-click="menu.toggleMenu()"`
が↓
`ng-switch="$ctrl.loader.getCurrentState()" ` `ng-click="$ctrl.menu.toggleMenu()"`
のように、`$ctrl`を使ってコントローラ内のメンバを呼ぶように変更されている。

コントローラの中身は以下の通り。 

```js:www/js/app-group-list.js
(function() {
    'use strict';
    var app = angular.module('app');

    // コントローラ
    function controller($http, $timeout, Config) {
        var vm = this;

        // メンバ
        vm.menu = null;
        vm.loader = null;
        vm.groupList = null;
        vm.loadGroupList = loadGroupList;
        
        // グループ一覧取得
        function getGroupList($done) {
            // HTTPリクエスト
            var params = {};
            $http({
               method  : 'GET',
               url     : Config.getUrl() + '/api/user/groupl.do',
               timeout : 10000,
               params  : params,
            }).success(function(data, status, headers, config) {
               self.groupList = data.ResultSet.Result;
            }).error(function(data, status, headers, config) {
                ons.notification.alert({
                    message     : '通信に失敗しました',
                    title       : '通信エラー',
                    buttonLabel : 'OK'
                });
            }).finally(function() {
                $done();
            });
        }
        
        // プルフック読み込み
        this.load = function($done) {
            getGroupList($done);
        }
        
        // 読み込み時
        ons.ready(function() {
            $timeout(function() {
                self.menu = window.menu;
                self.loader = window.loader;
                self.load();
            });
        });
    }
    
    // DI
    controller.$inject = ['$http', '$timeout', 'Config'];

    // コンポーネントオブジェクト
    var component = {
        bindings : {
            title : '@'
        },
        controller : controller,
        templateUrl : 'templates/group-list.html'        
    }
    
    // コンポーネント登録
    app.component('groupList', component);

})();
```

ごく当たり前の方法だが`$timeout`の存在を忘れていると未定義エラーが起きたりしてハマる。
読み込みのタイミング的にmenuは必ずしも`$timeout`の中で代入する必要はない。

# 結論
Componentを用いる場合、ons-sliding-menu や ons-pull-hook のvarはそのままでは使えない。

```js
ons.ready(function() {
    $timeout(function() {
        self.menu = window.menu;
        self.loader = window.loader;
    });
});
```

のように代入してから`$ctrl`経由でアクセスすべし。