ng-scrollbar无法使用ng-repeat

时间:2014-07-09 21:13:59

标签: angularjs angularjs-ng-repeat

在我的应用中,我想使用div的自定义滚动条。所以我使用了ng-scrollbar,它可以很好地处理静态数据。但每当我使用ng-repeat获取数据时,它都无法正常工作。请帮助我这方面。提前谢谢。

myFile.html

<style>
  .scrollme {
    max-height: 300px;
   }
</style>

<div ng-app="myapp">
  <div class="container" ng-controller="myctrl">

    <button class="btn btn-info" ng-click="add();">add</button>
    <button class="btn btn-warning" ng-click="remove();">remove</button>

    <div class="well" >
      <div class="scrollme" ng-scrollbar bottom rebuild-on="rebuild:me">
        <h1>Scroll me down!</h1>
        <p ng-repeat="mi in me">{{mi.name}}</p>
      </div>
    </div>
  </div>
</div>

myCtrl.js

var myapp = angular.module('myapp', ["ngScrollbar"]);
myapp.controller('myctrl', function ($scope) {
    $scope.me = [];
    for(var i=1;i<=20;i++){
        $scope.me.push({"name":i});
    }
    var a = $scope.me.length;
    $scope.add = function(){        
    $scope.me.push({"name":$scope.me.length+1});
    $scope.$broadcast('rebuild:me');
    }
    $scope.remove = function(){
        $scope.me.pop();
    }
});

4 个答案:

答案 0 :(得分:2)

尝试将broadcast调用添加到控制器的末尾,以便在控制器负载上触发。如果这不起作用,请尝试添加:

$timeout(function () {
    $scope.$broadcast('rebuild:me');
}, 0);
// 0 optional, without it the time is assumed 0 which means next digest loop.

在控制器代码的末尾,而不是在add函数内。如果这样做但前一种方法不起作用那么这意味着ngRepeat没有及时完成呈现它的动态内容,以便ngScrollbar正确更新。

更新:通常,您可能必须在超时中包装add()函数内的广播。我说这个的原因是我怀疑发生了什么是你将数据添加到范围变量然后在同一个函数调用中广播。可能发生的事情是在ngRepeat看到更新的范围数据并添加其额外的DOM元素之前捕获广播事件并重新计算滚动条。顺便说一句,如果你想重新计算add()上的滚动条,那么你也想在remove()上做这个。

所以你的添加功能将成为:

$scope.add = function(){        
    $scope.me.push({"name":$scope.me.length+1});
    // wait until next digest loop to send event, this way ngRepeat has enough time to update(?)
    $timeout(function () {
        $scope.$broadcast('rebuild:me');
    });
}

答案 1 :(得分:0)

请尝试ng-scroll ...另一个插件,但无需手动调整。 提及:

AngularJS with ng-scroll and ng-repeat

答案 2 :(得分:0)

如果你使用jQuery,你可以尝试jQuery Scrollbar - 它有更多options和完全CSS可自定义。

ng-repeat的示例是here

<强>的JavaScript

var demoApp = angular.module('demoApp', ['jQueryScrollbar']);

demoApp.controller('SimpleController', function($scope){

    $scope.me = [];
    for(var i=1;i<=20;i++){
        $scope.me.push({"name":i});
    }

    $scope.add = function(){
        $scope.me.push({"name":$scope.me.length+1});
    }
    $scope.remove = function(){
        $scope.me.pop();
    }

    $scope.jqueryScrollbarOptions = {
        "onUpdate":function(container){
            setTimeout(function(){
                // scroll to bottom. timeout required as scrollbar restores
                // init scroll positions after calculations
                container.scrollTop(container.prop("scrollHeight"));
            }, 10);


        }
    };
});

<强> HTML

<div data-ng-app="demoApp">
    <div data-ng-controller="SimpleController">
        <button class="btn btn-info" ng-click="add();">add</button>
        <button class="btn btn-warning" ng-click="remove();">remove</button>
        <div class="scrollbar-dynamic" data-jquery-scrollbar="jqueryScrollbarOptions">
            <h1>Scroll me down!</h1>
            <p ng-repeat="mi in me">{{mi.name}}</p>
        </div>
    </div>
</div>

<强> CSS

.scrollbar-dynamic {
    border: 1px solid #FCC;
    max-height: 300px;
    overflow: auto;
}

答案 3 :(得分:0)

这可能有点晚了。

即使您已将内容添加到范围变量,问题仍然存在,angular尚未完成向您的DOM添加p标记。如果您尝试一个简单的控制台日志,如

console.log($('.well').find('p').length);

将内容推送到$scope.me后,您将了解正在发生的事情。 (至少需要jQuery来调试)

解决方案远比你想象的要复杂得多。

第1步:

ng-controller添加ng-repeat(是。允许)

<p ng-repeat="mi in me" ng-controller="loopController">{{mi.name}}</p>

第2步:定义loopController

demoApp.controller('loopController', function($scope) {
    $scope.$watch('$last', function(new_val) {
        new_val && $scope.$emit('loopLoaded', $scope.$index);
    });
});

只要ng-repeat操纵DOM,就会触发此控制器功能。我正在观看$last这是ng-repeat的范围变量。只要ng-repeat加载DOM中的最后一个元素,就会将其设置为true。当$last设置为true时,我会发出一个事件loopLoaded。由于您使用循环将值推送到$scope.me,因此每次推送都会触发此事件。


第3步:事件处理

在你的SimpleController中(不再简单,嗯?)

$scope.$on('loopLoaded', function(evt, index) {
    if (index == $scope.me.length-1) {
        $scope.$broadcast('rebuild:me');
    }
});

加载所有p元素后,发送到事件的index将等于$scope.me.length-1。所以你调用scroll rebuild。那就是它。

以下是我使用过的参考资料 - AngularJS - Manipulating the DOM after ng-repeat is finished