0

This Angular script gets content from an API and I implemented ngInfiniteScroll to avoid getting the whole content at once from the source. When the ngInfiniteScroll function fires to load the second page, you can see the content load for a fraction of second but then the whole div disappears. Any idea why?

LIVE EXAMPLE

http://nolayout.com/archive/index-2.html

ANGULAR SCRIPT

var app = angular.module('arenaApp', ['ngResource', 'ngSanitize', 'infinite-scroll']);

    app.controller('channelShow', function($scope, $resource, $routeParams, $rootScope) {

        var Channel = $resource('http://api.are.na/v2/channels/:slug/contents');
        $scope.channel = [];
        var channel = Channel.get({ slug: 'no-layout-archive', per: 20, sort: 'position', direction: 'asc' }, function() {
            $scope.channel = channel;
        });

        $scope.busy = false;
        $scope.page = 1;

        $scope.appendContents = function() {
            if ($scope.busy) return;
            $scope.busy = true;
            $scope.page++;
            var channel = Channel.get({ slug: 'no-layout-archive', per: 20, page: $scope.page, sort: 'position', direction: 'asc' }, function() {
                    $scope.channel = channel;
                    $scope.busy = false;
            });
        }
    });

HTML

<div class="container" infinite-scroll="appendContents()" infinite-scroll-disabled="busy" infinite-scroll-distance="1" >
    <div ng-repeat="block in channel.contents | filter:query" >
        <div ng-if="block.class == 'Image'">
            <div class="seven columns add-bottom imgnormal">
                <img src="{{block.image.original.url}}" alt="{{block.title}}">
            </div> 
        </div>
    </div>
    <div ng-show="busy">Loading</div>
</div>
neoswf
  • 4,269
  • 4
  • 35
  • 52
anoonimo
  • 337
  • 2
  • 3
  • 13
  • your $scope.appendContents is being call 6 times and your contents is exhausted in one scroll. you need to keep $scope.busy = false until the image is loaded or do something to increase the height of your container – wayne Mar 05 '14 at 00:59

1 Answers1

1
var app = angular.module('arenaApp', ['ngResource', 'ngSanitize', 'infinite-scroll']);

    app.controller('channelShow', function($scope, $resource, $routeParams, $rootScope) {

        var Channel = $resource('http://api.are.na/v2/channels/:slug/contents');

        // change this
        // $scope.channel = [];
        $scope.channel = {contents:[]};

        // remove this, double request
        // var channel = Channel.get({ slug: 'no-layout-archive', per: 20, sort: 'position', direction: 'asc' }, function() {
            $scope.channel = channel;
        });

        $scope.busy = false;
        $scope.page = 1;

        $scope.imageloaded = function() {
          $scope.imagesloaded++;
          if ($scope.imagesloaded >= $scope.channel.contents.length)
            $scope.busy = false;
        }
        $scope.appendContents = function() {
            if ($scope.busy) return;
            $scope.busy = true;
            $scope.page++;
            var channel = Channel.get({ slug: 'no-layout-archive', per: 20, page: $scope.page, sort: 'position', direction: 'asc' }, function() {
                    // change this
                    // $scope.channel = channel;
                    $scope.channel.contents = $scope.channel.contents.concat(channel.contents);
                    $scope.imagesloaded = 0;
            });
        }
    });

// add a directive in javascript
app.directive("imageLoaded",  function() { 
    return {
      restrict: "A",
      link: function(scope, elem, attr) {
        elem.on('load', function() {
          scope.$parent.imageloaded();

        });
      }
    };
  });


<div class="container" infinite-scroll="appendContents()" infinite-scroll-disabled="busy" infinite-scroll-distance="1" >
    <div ng-repeat="block in channel.contents | filter:query" >
        <div ng-if="block.class == 'Image'">
            <div class="seven columns add-bottom imgnormal">
                <!-- use ng-src for image read: http://docs.angularjs.org/api/ng/directive/ngSrc  -->
                <img ng-src="{{block.image.original.url}}" image-loaded alt="{{block.title}}">
            </div> 
        </div>
    </div>
    <div ng-show="busy">Loading</div>
</div>
wayne
  • 3,230
  • 17
  • 11
  • Thank you. It now loads the second appendContents() correctly but instead of appending them below the existing content it replaces completely the first page with the second. See http://nolayout.com/archive/index-3.html – anoonimo Mar 05 '14 at 01:46
  • 1
    use Array.concat after you receive result in $scope.channel – wayne Mar 05 '14 at 01:48
  • I tried unsuccessfully, if you have the patience of showing me how I'll greatly appreciate (I'm very novice, learning the hard way). – anoonimo Mar 05 '14 at 02:12
  • Last question, feel free to ignore. The concat worked but I still have the issue of the container: it loads correctly the second page of images, but not the third and so on because it doesn't detect the end of the container... – anoonimo Mar 05 '14 at 05:03
  • are you sure the infinite-scroll detection not kick in? I am thinking the directive imageLoaded. If one of your image is not fully loaded/error, $scope.busy will forever be false again. I can't test so I can't tell you. you need to step through that part. maybe change ($scope.imagesloaded >= $scope.channel.contents.length), if half of the images are loaded then set it to true. – wayne Mar 05 '14 at 06:10