※記事の内容は相当古いです。AngularJSではなく、Angularを使いましょう。
記事の対象者
- OnsenUIを使っている人
- AngularJS1.5のComponentを使いたい人
問題
新しいものが好きだ。
Angular2への移行を見越してComponentベースで実装してみたはいいが、
・ ons-sliding-menu とか
・ ons-pull-hook
がうまく動かない。
具体的には、templateUrlで指定した「***.html」内の
・ menu.toggleMenu()が動かない
・ loader.getCurrentState()が動かない
解決策
コンポーネントのテンプレートではvarを直接参照できないので、$ctrlからアクセスするように変更する。
方法
例えばこんな感じにページを作ったとする。
スライドメニューがあって、何かの一覧表示のためのコンポーネントが入っている。
<!-- グループ一覧ページ -->
<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コンポーネントのテンプレートはこちら。
<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
を使ってコントローラ内のメンバを呼ぶように変更されている。
コントローラの中身は以下の通り。
(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
経由でアクセスすべし。