AngularJSで無限スクロール

こんにちは。今日は暖かい日和です。もう3月ですね。

さて、放置気味だったAngularJSの勉強を再開しました。 とりあえずこの本を読んでいます。
良い本と思います。

さて、Twitterのタイムラインのような無限スクロールをAngularJSで作るとどういう感じになるのかな、ということを調べてみました。

ググってみると、ズバリなものが見つかります。
ngInfiniteScroll
これでええやん、という話ですが、今回はもっと軽い実装を探してみます。

そうすると、こういうものがJSFiddleにアップされています。
AngularJS: Infinite Scrolling
なるほど、AngularJSではコレクションのレンダリングは自動でやってくれるので、一番下までスクロールしたタイミングでコレクションにデータを追加してやれば簡単にできるようです。

これを参考にして実装してみました。

Template

無限スクロールを表示する部分です。

<div class='content' when-scrolled='loadMore()'>
<ul ng-repeat='d in data'>
  <li>{{d}}</li>
</ul>
</div>

dataという名前のコレクションをリスト表示しています。 リストを囲っているdivにwhen-scrolledというディレクティブを指定しています。

Directive

whenScrolledディレクティブです。
一番下までスクロールしたらattributeの値を実行するようにします。
つまりコントローラーのloadMoreを実行します。

angular.module('myApp.directives', []).
  directive('appVersion', ['version', function(version) {
    return function(scope, elm, attrs) {
      elm.text(version);
    };
  }])
  .directive('whenScrolled', function($window) {
    return function(scope,  elem,  attr) {
      var raw = elem[0];
      angular.element($window).bind('scroll',  function() {
        if (raw.offsetTop + raw.offsetHeight < document.documentElement.scrollTop + window.innerHeight) {
          scope.$apply(attr.whenScrolled);
        }
      });
    };
  });

Controller

コントローラーはInfiniteScrollCtrlです。
初期時には25個の要素をdataに入れます。
loadMoreメソッドがコールされると、dataに25個追加します。
これにより無限スクロールするように見えます。

angular.module('myApp.controllers', []).
  controller('MyCtrl1', [function() {

  }])
  .controller('MyCtrl2', [function() {

  }])
  .controller('InfiniteScrollCtrl', ['$scope', function($scope) {
    var i = 0,
        data = [];
    for(i = 0; i < 25; i++) {
      data.push(i);
    }
    $scope.data = data;
    $scope.next = data.length;

    $scope.loadMore = function() {
      if ($scope.next === i + 25) {
        return;
      }
      $scope.next = i + 25;

      for(; i < $scope.next; i++) {
        data.push(i);
      }
    };
  }]);

まとめ

データを増やせば自動でレンダリングされるので、jQueryなどで実装するよりコード量が減りますね。
ここに実装おいてます。

Comments