我想调用一些jQuery函数,以div为目标。该表填充了ng-repeat
。
当我在
上打电话时$(document).ready()
我没有结果。
另外
$scope.$on('$viewContentLoaded', myFunc);
没有帮助。
有没有办法在ng-repeat群体完成后立即执行功能?我已经阅读了有关使用自定义directive
的建议,但我不知道如何将其与ng-repeat和我的div一起使用...
答案 0 :(得分:238)
实际上,你应该使用指令,并且没有事件与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中查看此操作。希望它有所帮助!
答案 1 :(得分:67)
如果你只是想在循环结束时执行一些代码,这里的变化稍微简单一些,不需要额外的事件处理:
<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');
}
};
});
答案 2 :(得分:58)
不需要创建指令,尤其是只有ng-repeat
完成事件。
ng-init
为你带来了魔力。
<div ng-repeat="thing in things" ng-init="$last && finished()">
$last
确保finished
仅在最后一个元素呈现给DOM时被触发。
不要忘记创建$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
元素的顶部添加上面的行。它将检查数组是否没有任何值并相应地调用该函数。
E.g。
<div ng-if="things.length > 0" ng-init="finished()"></div>
<div ng-repeat="thing in things" ng-init="$last && finished()">
答案 3 :(得分:40)
这是一个repeat-done指令,在true时调用指定的函数。我发现在执行DOM操作之前,被调用的函数必须使用$ timeout和interval = 0,例如在渲染元素上初始化工具提示。 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...
}
})
答案 4 :(得分:29)
这是使用ng-init
的简单方法,甚至不需要自定义指令。在某些情况下,它对我很有用,例如需要在页面加载时自动滚动一系列ng重复项目到特定项目,因此滚动功能需要等到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内容时调用函数,那么您必须使用自定义指令在此线程上使用其他答案之一。
答案 5 :(得分:27)
补充Pavel的answer,更具可读性和易懂性的是:
<ul>
<li ng-repeat="item in items"
ng-init="$last ? doSomething() : angular.noop()">{{item}}</li>
</ul>
为什么你认为angular.noop
首先出现在那里......?
<强>优点:强>
你不必为此写一个指令......
答案 6 :(得分:20)
使用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 使用预链接编译阶段 - 即在处理子指令之前调用表达式。这意味着可能仍需要异步处理。
答案 7 :(得分:4)
当您检查scope.$last
变量以使用setTimeout(someFn, 0)
包裹触发器时,可能还需要这样做。 setTimeout 0
是javascript中可接受的技术,我的directive
必须正确运行。
答案 8 :(得分:3)
这是对其他答案中表达的观点的改进,以展示在使用声明性语法时如何获取对ngRepeat属性($ index,$ first,$ middle,$ last,$ even,$ odd)的访问权限使用元素指令隔离范围(Google建议的最佳实践)。请注意主要区别:scope.$parent.$last
。
angular.module('myApp', [])
.directive('myRepeatDirective', function() {
return {
restrict: 'E',
scope: {
someAttr: '='
},
link: function(scope, element, attrs) {
angular.element(element).css('color','blue');
if (scope.$parent.$last){
window.alert("im the last!");
}
}
};
});
答案 9 :(得分:3)
<div ng-repeat="i in items">
<label>{{i.Name}}</label>
<div ng-if="$last" ng-init="ngRepeatFinished()"></div>
</div>
我的解决方案是添加一个div来调用函数,如果该项是重复的最后一个。
答案 10 :(得分:2)
我想添加另一个答案,因为前面的答案认为在完成ngRepeat之后运行所需的代码是一个角度代码,在这种情况下,上面的所有答案都提供了一个非常简单的解决方案,一些更通用与其他人一样,如果它在摘要生命周期阶段很重要,你可以看一下它的Ben Nadel's blog,除了使用$ parse而不是$ eval。
但根据我的经验,正如OP所述,它通常在finnaly编译的DOM上运行一些JQuery插件或方法,在这种情况下我发现最简单的解决方案是使用setTimeout创建一个指令,因为setTimeout函数被推送到浏览器队列的末尾,它总是在一切都以角度完成之后,通常是ngReapet,它在父母postLinking函数之后继续
angular.module('myApp', [])
.directive('pluginNameOrWhatever', function() {
return function(scope, element, attrs) {
setTimeout(function doWork(){
//jquery code and plugins
}, 0);
};
});
对于谁想知道在那种情况下为什么不使用$ timeout,它会导致另一个完全没有必要的摘要周期
答案 11 :(得分:2)
我是这样做的。
创建指令
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);
将其添加到此ng-repeat
的标签上<ul>
<li ng-repeat="(key, value) in data" fin-repeat> {{ value }} </li>
</ul>
准备就绪将在ng-repeat结束时运行。
答案 12 :(得分:1)
我必须在ng-repeat结束后使用MathJax渲染公式,上述答案都没有解决我的问题,所以我做了如下。这是不是一个好的解决方案,但对我有用......
<div ng-repeat="formula in controller.formulas">
<div>{{formula.string}}</div>
{{$last ? controller.render_formulas() : ""}}
</div>
答案 13 :(得分:0)
我找到了一个很好的答案here,但仍然需要添加延迟
创建以下指令:
angular.module('MyApp').directive('emitLastRepeaterElement', function() {
return function(scope) {
if (scope.$last){
scope.$emit('LastRepeaterElement');
}
}; });
将其作为属性添加到转发器中,如下所示:
<div ng-repeat="item in items" emit-last-repeater-element></div>
Radu说:
$scope.eventoSelecionado.internamento_evolucoes.forEach(ie => {mycode});
对我来说它有效,但我仍然需要添加一个setTimeout
$scope.eventoSelecionado.internamento_evolucoes.forEach(ie => {
setTimeout(function() {
mycode
}, 100); });
答案 14 :(得分:-4)
如果你只是想改变类名,那么它将以不同的方式呈现,下面的代码可以解决问题。
<div>
<div ng-show="loginsuccess" ng-repeat="i in itemList">
<div id="{{i.status}}" class="{{i.status}}">
<div class="listitems">{{i.item}}</div>
<div class="listitems">{{i.qty}}</div>
<div class="listitems">{{i.date}}</div>
<div class="listbutton">
<button ng-click="UpdateStatus(i.$id)" class="btn"><span>Done</span></button>
<button ng-click="changeClass()" class="btn"><span>Remove</span></button>
</div>
<hr>
</div>
当我有类似的要求以Strick trough字体在我的购物清单中呈现购物项目时,此代码对我有用。