收到此错误:Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
我使用AngularJS创建了一个reddit样式的嵌套注释系统。但是在10级之后我在我的控制台上得到一个非常难看的错误,如下所示:
这恰好发生在10个深度之后:
嵌套注释是如下所示的指令:
commentCont.tpl.html:
<div class="comment-cont">
<div
class="upvote-arrow"
ng-show="!collapsed"
ng-click="vote()"
ng-class="{'active' : node.votedByMe}"
>
<div class="upvote-arrow-top"></div>
<div class="upvote-arrow-bottom"></div>
</div>
<div class="wrapper">
<div class="info">
<span class="collapse" ng-click="collapsed = !collapsed">[ {{collapsed ? '+' : '–'}} ]</span>
<span ng-class="{'collapsed-style' : collapsed}">
<a ui-sref="main.profile({id: node.userId})">{{node.username}}</a>
<span>{{node.upvotes}} point{{node.upvotes != 1 ? 's' : ''}}</span>
<span mg-moment-auto-update="node.createdTime"></span>
<span ng-show="collapsed">({{node.children.length}} child{{node.children.length != 1 ? 'ren' : ''}})</span>
</span>
</div>
<div class="text" ng-bind-html="node.comment | autolink | nl2br" ng-show="!collapsed"></div>
<div class="reply" ng-show="!collapsed">
<span ng-click="formHidden = !formHidden">reply</span>
</div>
</div>
<div class="input-area" ng-show="!collapsed">
<form ng-show="!formHidden" name="form" autocomplete="off" novalidate ng-submit="submitted = true; submit(formData, form)">
<div class="form-group comment-input-feedback-branch has-error" ng-show="form.comment.$invalid && form.comment.$dirty">
<div ng-messages="form.comment.$error" ng-if="form.comment.$dirty">
<div class="input-feedback" ng-message="required">Comment text is required.</div>
<div class="input-feedback" ng-message="maxlength">Comment text cannot exceed 2500 characters.</div>
</div>
</div>
<div
class="form-group"
ng-class="{ 'has-error' : form.comment.$invalid && form.comment.$dirty, 'has-success' : form.comment.$valid }"
>
<textarea
name="comment"
class="textarea comment-cont-textarea"
ng-model="formData.comment"
required
ng-maxlength="2500"
textarea-autoresize
></textarea>
</div>
<div class="form-group">
<mg-button-loading
mgbl-condition="awaitingResponse"
mgbl-text="Save"
mgbl-loading-text="Saving..."
mgbl-class="btn-blue btn-small"
mgbl-disabled="!form.$valid"
></mg-button-loading>
<mg-button-loading
mgbl-text="Cancel"
mgbl-class="btn-white btn-small"
ng-click="formHidden=true;"
></mg-button-loading>
</div>
</form>
</div>
<div ng-show="!collapsed">
<div ng-repeat="node in node.children" ng-include="'commentTree'"></div>
</div>
</div>
commentCont.directive.js:
(function () {
'use strict';
angular
.module('app')
.directive('commentCont', commentCont);
/* @ngInject */
function commentCont ($http, user, $timeout) {
return {
restrict: 'E',
replace: true,
scope: {
node: '='
},
templateUrl: 'app/post/commentCont.tpl.html',
link: function (scope, element, attrs) {
var textarea = element.querySelector('.comment-cont-textarea');
var voteOK = true;
var action = '';
var userInfo = user.get();
scope.formHidden = true; // Do not ng-init="" inside an ng-repeat.
scope.collapsed = false; // Do not ng-init="" inside an ng-repeat.
// Autofocus textarea when reply link is clicked.
scope.$watch('formHidden', function(newValue, oldValue) {
if (newValue !== true) {
$timeout(function() {
textarea[0].focus();
});
}
});
scope.submit = function (formData, form) {
if (form.$valid) {
scope.awaitingResponse = true;
formData.parentId = scope.node.id;
formData.postId = scope.node.postId;
formData.type = 4;
formData.fromUsername = userInfo.username;
formData.toId = scope.node.userId;
formData.fromImage = userInfo.thumbnail36x36.split('/img/')[1];
// console.log(formData);
$http.post('/api/comment', formData)
.then(function (response) {
scope.awaitingResponse = false;
if (response.data.success) {
if (response.data.rateLimit) {
alert(rateLimitMessage);
return false;
}
// id and createdTime is sent with response.data.comment.
var c = response.data.comment;
var newCommentNode = {
id: c.id,
userId: userInfo.id,
username: userInfo.username,
parentId: formData.parentId,
comment: formData.comment,
upvotes: 0,
createdTime: c.createdTime,
votedByMe: false,
children: [],
postId: scope.node.postId
};
// console.log('user', user.get());
// console.log('scope.node', scope.node);
// console.log('response', response);
// console.log('newCommentNode', newCommentNode);
formData.comment = '';
form.comment.$setPristine();
scope.formHidden = true;
scope.node.children.unshift(newCommentNode);
}
});
}
};
scope.vote = function() {
if (voteOK) {
voteOK = false;
if (!scope.node.votedByMe) {
scope.node.votedByMe = true;
action = 'add';
} else {
scope.node.votedByMe = false;
action = 'remove';
}
var data = {
commentId: scope.node.id,
action: action
};
$http.post('/api/comment/vote', data)
.then(function (response) {
// console.log(response.data);
voteOK = true;
if (action === 'add') {
scope.node.upvotes++;
} else {
scope.node.upvotes--;
}
});
}
};
}
};
}
}());
正在调用树:
<script type="text/ng-template" id="commentTree">
<comment-cont
node="node"
></comment-cont>
</script>
<div ng-repeat="node in tree[0].children" ng-include="'commentTree'"></div>
如何获得超过10级嵌套ng-repeat而不会出现这样的错误?
答案 0 :(得分:3)
$ digest()的默认实现限制为10次迭代。如果在10次迭代后范围仍然很脏,则会从$ digest()抛出错误。
以下陈述是将摘要迭代限制配置为20的一种方法。
var app = angular.module('plunker', [], function($rootScopeProvider) {
$rootScopeProvider.digestTtl(20); // 20 being the limit of iterations.
});
但是你应该考虑稳定你的模型,而不是配置迭代的限制。
答案 1 :(得分:0)
我正在处理类似的问题。最终得到以下指令:
(function () {
'use strict';
angular
.module('app')
.directive('deferDom', ['$compile', ($compile) => {
return {
restrict: 'A',
compile: (tElement) => {
// Find, remove, and compile the li.node element.
let $el = tElement.find( "li.node" );
let transclude = $compile($el);
$el.remove();
return function($scope){
// Append li.node to the list.
$scope.$applyAsync(()=>{
tElement.append(transclude($scope));
});
}
},
};
}]);
})();