2016-04-26 50 views
2

我有一个AngularJS项目(我不使用JQuery),我需要显示一个用户的表格,并在用户滚动页面附近时加载更多。我试图在不依赖外部库的情况下实现这一点,因为这是我的要求的一部分。如何正确实现无JQuery滚动的AngularJS表?

我检查了几个例子,如this,thisthis

但到目前为止,我没有检查过的例子帮助我实现了无限滚动,如我所料。他们使用不同的方式来计算何时触发调用,其中一些值返回给我未定义(即人们说clientHeight和scrollHeight有不同的值,但对我来说它总是相同的,总高度包括滚动空间)。

我创建像下面这样的指令:

usersModule.directive('whenScrollEnds', function($window) { 
    return { 
     restrict: "A", 
     link: function(scope, elm, attr) { 

      angular.element($window).bind('scroll', function() { 

      var hiddenContentHeight = elm[0].scrollHeight - angular.element($window)[0].innerHeight; 

      if ((hiddenContentHeight - angular.element($window)[0].scrollY) <= (10)) { 
       angular.element($window)[0].requestAnimationFrame(function(){ 
       scope.$apply(attr.whenScrollEnds); 
       }) 
      } 

      }); 
     } 
    }; 
}); 

这类作品,但有下列问题/疑虑,我希望有人能向我解释:

  • 它触发太快。当我接近可滚动空间的底部时,我想要触发加载,例如接近90%左右。
  • scrollHeight只能通过elm [0]访问,angular.element($ window)[0]没有scrollHeight属性,所以它返回undefined,而elm [0]没有scrollY值。
  • 我得到的scrollY值是滚动条从顶部移动的距离减去滚动条的长度,但我觉得这个值是错误的。
  • 通过angular.element($ window)绑定滚动事件.bind正确的决定?

我该如何实现一个合适的无限滚动表?我使用了正确的变量吗?请提供仅使用Javascript和AngularJS的答案,JQuery或库解决方案不会帮助我。

回答

3

在检查了几个例子并试图避免那些使用JQuery作为解决方案的一部分之后,我找到了一种方法来完成这项工作。

首先我的指令,当滚动结束,将处理:

usersModule.directive('whenScrollEnds', function($window) { 
    return { 
     restrict: "A", 
     link: function(scope, elm, attr) { 
      var raw = elm[0]; 

      raw.addEventListener('scroll', function() { 
      if ((raw.scrollTop + raw.clientHeight) >= (raw.scrollHeight)) { 
       scope.$apply(attr.whenScrollEnds); 
      } 
      }); 
     } 
    }; 
}); 

我的观点有div像这里面的表格:

<div id="usersScrollable" when-scroll-ends="uc.loadMoreUsers()"> 
    <table id="tableUsers" class="table" ng-show="uc.users.length" > 
     <thead> 
     <tr> 
     <th>Email</th> 
     <th>Nombre Completo</th> 
     <th>Estado</th> 
     <th>Acción</th> 
     </tr> 
     </thead> 
     <tbody > 
     <tr ng-repeat="u in uc.users"> 
     <td>{{u.email}}</td> 
     <td>{{u.fullName}}</td> 
     <td>{{uc.getStateString(u.active)}}</td> 
     <td><button type="button" class="btn btn-primary" ng-click="uc.edit(u)">Editar</button></td> 
     </tr> 
     </tbody> 
    </table> 
    </div> 

确保包含该表的div是一个在听滚动结束的时候。这div必须有一个设置的高度,如果它不然clientHeight财产将与scrollHeight相同(不知道如果没有明确定义高度会发生什么,而不是设置您设置顶部或底部属性的高度)。

在我的控制器,loadMoreUsers()负责递增页面(如果有多个用户,每个呼叫我得到了总用户的,所以我可以做另一个请求有多少用户,我已经离开之前知道),也它调用向Web服务发出请求的函数。

0

与乌列Arvizu提供的解决方案的问题是,如果raw元素是空的,因为它在等待页面加载一个HTTP请求,以下所有raw.scrollTopraw.clientHeight)raw.scrollHeight都会有错误的尺寸和滚动不再工作了。

我建议这个其他解决方案基本上将滚动事件添加到$window而不缓存它,所以当收到Http响应时它的大小总是正确的。

(function() { 
    'use strict'; 

    angular.module('ra.infinite-scroll', []).directive('infiniteScroll', function ($window) { 
     return { 
      restrict: 'A', 
      scope: { 
       infiniteScrollCallbackFn: '&' 
      }, 
      link: function (scope, elem, attrs) { 
       var percentage = (attrs.infiniteScrollPercentage !== undefined ? (attrs.infiniteScrollPercentage/100) : '.9'); 
       var $element = elem[0]; 

       angular.element($window).on('scroll', function() { 
        if ((this.scrollY + this.innerHeight - $element.offsetTop) >= ($element.scrollHeight * percentage)) { 
         scope.$apply(scope.infiniteScrollCallbackFn); 
        } 
       }); 
      } 
     }; 
    }); 
})(); 

另外,在该模块中,可以通过2个参数中的HTML:一个回调函数和特定元件的百分比(其中模块被施加)在达到时,它的回调函数被调用,即重复Http请求(默认是该元素的90%)。

<div infinite-scroll infinite-scroll-callback-fn="callBackFunction()" infinite-scroll-percentage="80"> 
     // Here you may include the infinite repeating template 
    </div>