【onsenui】無限スクロールを実装する
はじめに
今回やりたかったのはよくある無限スクロール。
リストの1番下までスクロールしたら次のデータを取得しにゆきます。
これをAngular + Onsen UIで実装したのでメモしておく。

データ数の多いリストはパフォーマンス的にons-lazy-repeatを使うとよいらしい。
そちらについてはこちらでも試してみた。
実装
テンプレート
HTMLはこんな感じで実装。ons-lazy-repeatを使った基本的な形。
リストの最下部に読込中アイコンを置いて、状態によって表示・非表示を切り替えるようにする。
<ons-page ng-controller="MainCtrl">
<ons-toolbar>
<div class="center">リスト</div>
</ons-toolbar>
<ons-list>
<ons-list-item ons-lazy-repeat="delegate">
{{ item.name }}
</ons-list-item>
</ons-list>
<ons-row ng-if="progress">
<ons-col style="text-align:center;">
<ons-icon size="30px" spin icon="md-spinner"></ons-icon>
</ons-col>
</ons-row>
</ons-page>
メイン処理
必要な処理としては以下
・APIに接続してデータを取得してくる
・1番下までスクロールしたらAPIに接続して次のデータを取得しにいく
1番下までスクロールしたかの判定はこんな感じ
.page__contentを対象にするのがポイントぽい
angular.module('sampleListApp')
.controller('MainCtrl', function () {
$('.page__content').on('scroll', function(e){
var elm = $(e.currentTarget);
if (elm[0].scrollHeight <= elm.height() + elm.scrollTop()) {
// ココに1番下までスクロールした時の処理を記述
}
});次はAPI接続部分
適当だけどAPIからはこんな感じのJSONが返ってくる想定
{
contents: [
{id:1, "アイテム1"},
{id:2, "アイテム2"},
{id:3, "アイテム3"},
・・・
]
}取得部分をfactoryとして外だし
angular.module('SampleApp')
.factory("ApiManager", function($http) {
return {
callApi: function(offset, callback) {
$http({
method: 'GET',
url: "http://path/to/api?offset="+offset
}).then(function successCallback(response) {
callback(respons.contents);
}, function errorCallback(response) { });
}
};
});で、完成形はこんな感じに
angular.module('sampleApp')
.controller('MainCtrl', function ($scope, $http, ApiManager) {
$scope.items = [];
$scope.progress = true;
ApiManager.callApi(0, function(contents) {
$scope.items = contents;
$scope.progress = false;
});
$('.page__content').on('scroll', function(e){
var elm = $(e.currentTarget);
if ($scope.progress == false &&
elm[0].scrollHeight <= elm.height() + elm.scrollTop()) {
$scope.progress = true;
ApiManager.callApi($scope.items.length, function(contents) {
for (var i = 0; i < contents.length; i++) {
$scope.items.push(contents[i]);
}
$scope.progress = false;
});
}
});
$scope.delegate = {
configureItemScope: function(index, itemScope) {
itemScope.item = $scope.items[index];
},
countItems: function() {
return $scope.items.length;
}
};
});また、ずらずらかいたけど以上です。