2014-07-09 50 views
3

在我的應用程序中,我想爲div使用自定義滾動條。所以我用ng-scrollbar,它對靜態數據工作正常。但是每當我使用ng-repeat來獲取數據時,它都不起作用。在這方面請幫助我。提前致謝。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(); 
    } 
}); 
+0

沒有滾動條的工作,一旦你點擊添加按鈕?有兩件事:你可能想要將重建:me事件添加到scope.remove中,因爲當你有一個添加時,告訴滾動條更新,當刪除時也會更新。您可能還想在控制器的末尾添加事件廣播,以便在初始渲染時觸發,而無需單擊add()。可能必須進入$ timeout(fund(){},0)以允許ngRepeat呈現,idk。 – jCuga

回答

2

嘗試添加broadcast呼叫控制器的末尾,以便它觸發控制器上的負載。如果不起作用,請嘗試添加:

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

在控制器代碼的末尾,而不是添加功能的內部。如果這樣做,但以前的方法並不那麼這意味着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'); 
    }); 
} 
+0

這也是行不通的。 $ broadcast('buildScrollbar'); **而不是_ $ scope。$ broadcast('rebuild:me'); _。我在_ngScrollbar.js_中移除了調用buildScrollbar()函數。在開始時顯示完美,但是當我點擊添加按鈕時,我的div高度正在下降。點擊4到5次後,div高度完全消失。 –

0

如果你使用jQuery,你可以嘗試jQuery Scrollbar - 它有更多的options,充分CSS定製。

實施例與NG-重複是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; 
} 
0

這可能有點晚。

問題是,即使您已將內容添加到作用域變量,角度還沒有完成將p標籤添加到您的DOM。如果你嘗試一個簡單的控制檯日誌一樣

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

內容推送到$scope.me之後,你就會明白髮生了什麼。(至少需要jQuery來調試)

該解決方案比您想象的要複雜得多。

第1步:

添加ng-controllerng-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,因此每次推送都會觸發此事件。


STEP 3:事件處理

在你SimpleController(不是簡單了,不是嗎?)

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

一旦所有的p元素被加載,index發送到事件會等於$scope.me.length-1。所以你調用滾動重建。而已。

下面是我用了一個參考 - AngularJS - Manipulating the DOM after ng-repeat is finished

+1

這太複雜了,但基本上是最好的解決方案。 當$ watch($ last)函數參數不是一個值時,它是一個「isLast」值,它會傳遞false直到最後一個項達到true。這意味着你可以在那裏發佈「重建:我」。不需要回調主控制器並測試長度。 – Adaddinsane

相關問題