4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-03-26

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

記事の対象者

  • OnsenUIを使っている人
  • AngularJS1.5のComponentを使いたい人

問題

新しいものが好きだ。

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

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

解決策

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

方法

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

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コンポーネントのテンプレートはこちら。

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を使ってコントローラ内のメンバを呼ぶように変更されている。

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

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はそのままでは使えない。

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

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

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?