Serviceを使ってみる
MVCのV(html),C(Controller)に続き、Mの役割を担うServiceを使ってみます。
Model関連の処理をService内にカプセル化することにより、バックエンドをMySQLだろうがOracleだろうがGoogle Cloud Endpointsだろうが、他のレイヤーに影響を与えず自由自在に切り替えらえるわけです。
実際にはバックエンドを切り替えることはほぼ無い(ですよね?)ので、 ここでは実践的な例として、まずモックアップ用のデータを扱うサービスを作ってみます。
中身
app.factory('OSService', function () {
var service = {};
var oss= [
{"name":"KiKat", "kind":"android", "desc":"androidos4.4系です"},
{"name":"JellyBean", "kind":"android", "desc":"androidos4.1-3系です"},
{"name":"Honycomb", "kind":"android","desc":"androidos3.x系です"},
{"name":"Mavericks", "kind":"osx","desc":"Mac 10.9"},
{"name":"Mountain Lion", "kind":"osx", "desc":"Mac 10.8"},
{"name":"Lion", "kind":"osx","desc":"Mac 10.7"},
{"name":"SnowLeopard", "kind":"osx", "desc":"Mac 10.6"},
];
/**
* OSのリストを取得する
* この関数内で遅延が発生しても良いようにcallbackで返す
*/
service.getOSList= function(callback) {
callback(oss);
}
// serviceオブジェクトを返す
return service;
});
js/controller/page1controller.js を修正
app.controller('Page1Ctrl',function($scope, OSService){ // OSServiceをインジェクト
/**
* 検索結果を受け取るコールバック関数
*/
var searchCallback = function(data){
$scope.oss = data;
};
OSService.getOSList(searchCallback);
}) ;
index.htmlにosservice.jsの読み込みを追加
.
.
<link rel="stylesheet" href="css/style.css">
<script src="js/controller/page1controller.js"></script>
<script src="js/service/osservice.js"></script> <!-- 追加 -->
<script>
var app = ons.bootstrap();
.
.
どうでしょうか。プレビューするとまったく変わらない結果が表示されるはずです。
ポイントは、Controller側でOSService
を使用するためにインジェクトしている箇所と、検索の遅延を考慮して検索結果をコールバック関数経由でControllerに返しているところです。javascriptぽいですね。
本当に遅延に対応しているのかよ?ということで、遅延するようコードを修正
.
.
service.getOSList= function(callback) {
setTimeout(function(){callback(oss)},3000); //3秒待って結果を返す
}
.
.
どうでしょう?プレビューしたら表示されましたか?されませんね。
AngularJSに$scope.oss
が更新されたことを通知する必要があるようです。
というわけでpage1controller.js
を修正
.
.
var searchCallback = function(data){
$scope.oss = data;
$scope.$apply(); // VIEWを更新する
};
.
.
これで3秒後にOSの一覧が表示されるはずです。
さらにpage1.html
を修正して読み込み待ちを表示してみます。
<ons-page>
<div ng-controller="Page1Ctrl">
<ons-toolbar>
<div class="center">List With Header</div>
</ons-toolbar>
<div ng-if="!!oss">
<!-- ossが無い場合は表示しない-->
<ons-list>
<ons-list-header>Android Versions</ons-list-header>
<ons-list-item modifier="chevron" ng-repeat="os in oss" ng-if="os.kind == 'android'">
{{os.name}}
</ons-list-item>
<ons-list-header>MacOSX Versions</ons-list-header>
<ons-list-item modifier="chevron" ng-repeat="os in oss" ng-if="os.kind == 'osx'">
{{os.name}}
</ons-list-item>
</ons-list>
</div>
<div ng-if="!oss" style="text-align:center;">
<!-- ossが無い場合に読み込み待ちを表示 -->
<br>
<br>
<ons-icon icon="spinner" spin="true"></ons-icon>
</div>
</div>
</ons-page>
angularjsの機能であるng-if
を使ってoss
が無い場合の表示を制御しています。
これでまた一歩アプリっぽくなってきました!