2013-01-11 56 views
6

我正在嘗試使用bootstrap scollspy來突出顯示由角度中繼器生成的列表項。在角度模型更改後刷新Bootstrap ScrollSpy

我遇到的問題是,我正在從角度控制器刷新滾動插件,然後角度將模型更改應用到視圖。

確保在更新DOM本身(不僅僅是角模型)之後發生scrollspy('refresh')調用的角度方法是什麼?

模板:

<div class="span2" id="addressList"> 
    <ul class="nav nav-tabs nav-stacked affix"> 
     <li ng-repeat="addr in addresses"><a href="#{{addr.id}}">{{addr.id}}</a></li> 
    </ul> 
</div> 

控制器:

$scope.httpSuccessCallback = function (data) 
    $scope.addresses.push(data); 
    $('[data-spy="scroll"]').scrollspy('refresh'); //calls $('#addressList .nav > li > a') 
} 
+0

這可能已經說過1,000次了。但是你不想從你的控制器功能中進行DOM操作。你想要做的是創建一個處理所有它的指令。然後使用$ watch來觸發更新來更新它。 –

+0

我沒有在我的控制器中進行任何DOM操作。我試圖在角度生命週期中的適當點更新jQuery插件。似乎像$ watch可能仍然是正確的機制? –

+4

你正在從DOM中選擇一個元素,並綁定事件等等...... *那真的是我的意思是「DOM操作」。 Angular的文檔很好地講述了這一點。您不應該在控制器中引用DOM。 –

回答

4

如何我解決了這個,使用Blesh的回答

模板:

<body ng-app="address" ng-controller="AddressCtrl" scroll-spy="addresses"> 
    <div class="container"> 
     <form ng-submit="lookupAddress()"> 
     <input type="text" ng-model="addressText" /> 
     <button id="addressQueryBtn">Submit</button> 
     </form> 

     <div id="addressList"> 
     <ul> 
      <li ng-repeat="addr in addresses">{{addr}}</li> 
     </ul> 
     </div> 

    </div> 
    </body> 

角JS:

angular.module('address', []). 
directive('scrollSpy', function($timeout){ 
    return function(scope, elem, attr) { 
    scope.$watch(attr.scrollSpy, function(value) { 
     $timeout(function() { elem.scrollspy('refresh') }, 200); 
    }, true); 
    } 
}); 

function AddressCtrl($scope, $http) { 
    $scope.addresses = []; 

    $scope.lookupAddress = function() { 
    $scope.addresses.push($scope.addressText); 
    $scope.addressText = ''; 
    }; 
} 

的第三個參數scope.watch(...)是當監視的作用域var是一個對象或數組時,需要它。不幸的是,這個解決方案在評論中仍然導致無法識別的表達問題randomguy提及。我最終通過手錶功能中的using a timeout解決了這個問題。

5

不知道什麼關於滾動間諜,這裏是你通常如何想使用角度jQuery插件:

app.directive('scrollSpy', function(){ 
    return { 
    restrict: 'A', 
    link: function(scope, elem, attr) { 
     elem.scrollSpy({ /* set up options here */ }); 

     //watch whatever expression was passed to the 
     //scroll-spy attribute, and refresh scroll spy when it changes. 
     scope.$watch(attr.scrollSpy, function(value) { 
       elem.scrollSpy('refresh'); 
     }); 
    } 
    }; 
}); 

然後在HTML中:

<div scroll-spy="foo">Do something with: {{foo}}</div> 

上面的例子是非常通用的,但它基本上將你的插件應用到一個元素,每次改變$ scope.foo時都會調用'refresh'或其他任何東西。

我希望有幫助。

+0

因此,當$ watch觸發時,是否保證視圖已經呈現並且DOM操作是否與對象的更改一起生效?在我們刷新之前,必須更新DOM。 – randomguy

+1

這樣做時,我收到無法識別的表達式錯誤。我使用模型來更新錨點(href =「#category {{cat.id}}」),我認爲在$ Angular更新DOM之前,$ watch回調觸發*。引導滾動插件嘗試使用尚未解析的#category {{cat.id}},並提供錯誤。 – randomguy

+0

角度文檔提到了指令聲明的compile()函數中可用的pre和post-linking函數。後鏈接應該是安全的DOM工作。我不確定如何使用它。 http://docs.angularjs.org/guide/directive –

1

在Angular中使用Scrollspy有一些挑戰(可能爲什麼AngularUI截至2013年8月還不包括Scrollspy)。

  1. 無論何時更改DOM內容,您都必須刷新滾動條。

    這樣做可以像這裏所說的那樣通過$觀察元素並設置scrollspy('refresh')調用的超時值來完成。

  2. 如果您希望能夠使用導航元素來導航可滾動區域,則需要覆蓋導航元素的默認行爲。

這可以通過使用的preventDefault以防止導航並附加scrollTo功能來實現。

我拋出一個工作示例了在Plunker:http://plnkr.co/edit/R0a4nJi3tBUBsluBJUo2?p=preview

-1

我一直在尋找一個解決這個問題一段時間,但我沒能找到一個。我最終通過創建一個帶有幾個指令的滾動間諜服務來實現我自己的目標。

該服務將跟蹤所有窺探的部分及其偏移量。該指令將創建一個滾動事件,突出顯示導航項並告訴服務所有部分的位置。由於此實現不監視作用域變量,因此應用程序需要廣播消息來更新所有部分的偏移量。

你可以在Github上找到我的example