转到过滤的ng-repeat元素的位置

时间:2015-04-20 21:09:41

标签: angularjs angularjs-ng-repeat

我有一个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需要时间来显示它正在创建的部分。在此之前,元素(及其位置)不存在。

设置超时可能会有效,但这似乎很草率。

我怀疑我需要创建某种回调或承诺。是吗?

1 个答案:

答案 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之前滚动对于浏览器没有意义,所以你无法避免它(但你可以隐藏它)。