我有一个ng-repeat元素列表,它们根据范围内的布尔变量进行过滤。
HTML:
<button ng-click="toggleSection(1)">Section 1</button>
<button ng-click="toggleSection(2)">Section 2</button>
<button ng-click="toggleSection(3)">Section 3</button>
<div id="$index" ng-repeat="section in sections track by $index | filterSections">
...
</div>
过滤器:
myApp.filter('filterSections', function() {
return function(input) {
var returnArray = [];
$.each(input, function(index, bool) {
if (bool) returnArray.push(bool);
});
return returnArray;
}
})
并在我的控制器中:
$scope.sections = [false, false, false];
$scope.toggleSection = function(n) {
$scope.sections[n] = $scope.sections[n] ? false : true;
}
但是,我希望相同的toggleSection函数转到它显示的元素的位置,比如......
$scope.toggleSection = function(n) {
$scope.sections[n] = $scope.sections[n] ? false : true;
window.scrollTo($("#" + n).position().top, 0);
}
但我不能这样做,因为DOM需要时间来显示它正在创建的部分。在此之前,元素(及其位置)不存在。
设置超时可能会有效,但这似乎很草率。
我怀疑我需要创建某种回调或承诺。是吗?
答案 0 :(得分:1)
自定义指令,承诺或其他任何东西,如果你的动作(滚动)依赖于DOM(它确实如此),你就无法避免在角度摘要周期后执行它。
因此,做到这一点的简短方法确实是超时:
$scope.toggleSection = function(n) {
$scope.sections[n] = $scope.sections[n] ? false : true;
$timeout(function() {
window.scrollTo($("#" + n).position().top, 0);
}, 0, false);
}
注意$timeout
的第三个参数为false:这是因为在超时执行其回调之后你不需要$apply
范围(运行另一个摘要周期),因为它只是jQuery。< / p>
同样,在更新DOM之前滚动对于浏览器没有意义,所以你无法避免它(但你可以隐藏它)。