ng-repeat
填充的。当我在...(此处省略)
$(document).ready()
我没有任何结果。
另外
$scope.$on('$viewContentLoaded', myFunc);
有没有办法在 ng-repeat 完成后立即执行函数?我读到了一个使用自定义 directive
的建议,但是我不知道如何将它与 ng-repeat 和我的 div 一起使用...
ng-repeat
填充的。$(document).ready()
我没有任何结果。
另外
$scope.$on('$viewContentLoaded', myFunc);
有没有办法在 ng-repeat 完成后立即执行函数?我读到了一个使用自定义 directive
的建议,但是我不知道如何将它与 ng-repeat 和我的 div 一起使用...
确实,你应该使用指令,并且没有与ng-Repeat循环结束相关联的事件(因为每个元素都是单独构建的,而且有它自己的事件)。但是a)使用指令可能是你需要的全部内容;b)有一些ng-Repeat特定的属性可以用来创建“在ngRepeat完成时”的事件。
具体而言,如果你只想为整个表格设置样式/添加事件,可以在一个包含所有ngRepeat元素的指令中这样做。另一方面,如果你想分别处理每个元素,你可以在ngRepeat内部使用指令,它将在每个元素创建后发生作用。
然后,还有$index、$first、$middle和$last等属性可用于触发事件。因此,对于这个HTML:
<div ng-controller="Ctrl" my-main-directive>
<div ng-repeat="thing in things" my-repeat-directive>
thing {{thing}}
</div>
</div>
你可以这样使用指令:
angular.module('myApp', [])
.directive('myRepeatDirective', function() {
return function(scope, element, attrs) {
angular.element(element).css('color','blue');
if (scope.$last){
window.alert("im the last!");
}
};
})
.directive('myMainDirective', function() {
return function(scope, element, attrs) {
angular.element(element).css('border','5px solid red');
};
});
在这个Plunker中可以看到它的实际应用。
如果你只是想在循环结束时执行一些代码,这里有一个稍微简单一点的变体,不需要额外的事件处理:
<div ng-controller="Ctrl">
<div class="thing" ng-repeat="thing in things" my-post-repeat-directive>
thing {{thing}}
</div>
</div>
function Ctrl($scope) {
$scope.things = [
'A', 'B', 'C'
];
}
angular.module('myApp', [])
.directive('myPostRepeatDirective', function() {
return function(scope, element, attrs) {
if (scope.$last){
// iteration is complete, do whatever post-processing
// is necessary
element.parent().css('border', '1px solid black');
}
};
});
无需专门创建指令来实现ng-repeat
完成事件。
ng-init
可以为你完成这个魔术。
<div ng-repeat="thing in things" ng-init="$last && finished()">
$last
确保只有在最后一个元素被渲染到DOM时才触发 finished
事件。
不要忘记创建 $scope.finished
事件。
祝编码愉快!
编辑:2016年10月23日
如果您希望在数组中没有项目时也调用 finished
函数,则可以使用以下解决方法:
<div style="display:none" ng-init="things.length < 1 && finished()"></div>
//or
<div ng-if="things.length > 0" ng-init="finished()"></div>
只需将上述代码添加到 ng-repeat
元素的顶部,它会检查数组是否有任何值,并相应地调用函数。
例如:
<div ng-if="things.length > 0" ng-init="finished()"></div>
<div ng-repeat="thing in things" ng-init="$last && finished()">
以下是一个repeat-done指令,当值为true时调用指定函数。我发现被调用的函数必须使用interval=0的$timeout,然后再进行DOM操作,例如在渲染元素上初始化工具提示。 jsFiddle: http://jsfiddle.net/tQw6w/
在$scope.layoutDone中,尝试注释掉$timeout并取消注释“NOT CORRECT!”行,以查看工具提示中的差异。
<ul>
<li ng-repeat="feed in feedList" repeat-done="layoutDone()" ng-cloak>
<a href="{{feed}}" title="view at {{feed | hostName}}" data-toggle="tooltip">{{feed | strip_http}}</a>
</li>
</ul>
JS:
angular.module('Repeat_Demo', [])
.directive('repeatDone', function() {
return function(scope, element, attrs) {
if (scope.$last) { // all are rendered
scope.$eval(attrs.repeatDone);
}
}
})
.filter('strip_http', function() {
return function(str) {
var http = "http://";
return (str.indexOf(http) == 0) ? str.substr(http.length) : str;
}
})
.filter('hostName', function() {
return function(str) {
var urlParser = document.createElement('a');
urlParser.href = str;
return urlParser.hostname;
}
})
.controller('AppCtrl', function($scope, $timeout) {
$scope.feedList = [
'http://feeds.feedburner.com/TEDTalks_video',
'http://feeds.nationalgeographic.com/ng/photography/photo-of-the-day/',
'http://sfbay.craigslist.org/eng/index.rss',
'http://www.slate.com/blogs/trending.fulltext.all.10.rss',
'http://feeds.current.com/homepage/en_US.rss',
'http://feeds.current.com/items/popular.rss',
'http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml'
];
$scope.layoutDone = function() {
//$('a[data-toggle="tooltip"]').tooltip(); // NOT CORRECT!
$timeout(function() { $('a[data-toggle="tooltip"]').tooltip(); }, 0); // wait...
}
})
这里有一个简单的方法,使用ng-init
甚至不需要自定义指令。在某些情况下,例如需要在页面加载时将ng-repeat项目的div自动滚动到特定项目时,它对我很有效,因此滚动函数需要等待ng-repeat
完成DOM的渲染才能触发。
<div ng-controller="MyCtrl">
<div ng-repeat="thing in things">
thing: {{ thing }}
</div>
<div ng-init="fireEvent()"></div>
</div>
myModule.controller('MyCtrl', function($scope, $timeout){
$scope.things = ['A', 'B', 'C'];
$scope.fireEvent = function(){
// This will only run after the ng-repeat has rendered its things to the DOM
$timeout(function(){
$scope.$broadcast('thingsRendered');
}, 0);
};
});
请注意,这只适用于您需要在ng-repeat首次渲染后调用一次的函数。如果您需要在ng-repeat内容更新时调用函数,则必须使用本线程中的其他答案之一,配合自定义指令。
在补充 Pavel 的回答之后,更易读且易于理解的内容如下:
<ul>
<li ng-repeat="item in items"
ng-init="$last ? doSomething() : angular.noop()">{{item}}</li>
</ul>
你觉得为什么 angular.noop
会首先存在呢?
优点:
您不需要为此编写指令...
ng-init="$last && doSomething()"
。 - Nate Whittaker可以使用ngInit
和Lodash的debounce
方法,不需要自定义指令,以一种更简单的方式来处理:
控制器:
$scope.items = [1, 2, 3, 4];
$scope.refresh = _.debounce(function() {
// Debounce has timeout and prevents multiple calls, so this will be called
// once the iteration finishes
console.log('we are done');
}, 0);
模板:
<ul>
<li ng-repeat="item in items" ng-init="refresh()">{{item}}</li>
</ul>
使用三元运算符,甚至可以提供更简单的纯 AngularJS 解决方案:
模板:
<ul>
<li ng-repeat="item in items" ng-init="$last ? doSomething() : null">{{item}}</li>
</ul>
请注意,ngInit使用预链接编译阶段 - 即在处理子指令之前调用表达式。这意味着仍可能需要异步处理。
ng-init="$last ? refresh() : false"
也可以工作。而且这甚至不需要 Lodash。 - Pavel Horal当你检查scope.$last
变量时,可能需要用setTimeout(someFn, 0)
包装你的触发器。在javascript中,setTimeout 0
是一种被接受的技术,对于我的指令正确运行来说非常重要。
我用这种方式做了。
创建指令。
function finRepeat() {
return function(scope, element, attrs) {
if (scope.$last){
// Here is where already executes the jquery
$(document).ready(function(){
$('.materialboxed').materialbox();
$('.tooltipped').tooltip({delay: 50});
});
}
}
}
angular
.module("app")
.directive("finRepeat", finRepeat);
<ul>
<li ng-repeat="(key, value) in data" fin-repeat> {{ value }} </li>
</ul>
并已准备好在ng-repeat结束时运行。
<div ng-repeat="i in items">
<label>{{i.Name}}</label>
<div ng-if="$last" ng-init="ngRepeatFinished()"></div>
</div>