2013-01-11 30 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