Elliott McNary Elliott McNary - 5 months ago 126
AngularJS Question

AngularJS: Infinite $digest loop error?

I'm doing this tutorial and can't get my page to load correctly. I keep getting

Error: [$rootScope:infdig]
in the console.

I'm very new to Angular, but from what i've read I have an infinite loop somewhere. I anticipate it's from
o.getAll
, but I can't see how it's looping infinitely.

The entire error in the console is:

Error: [$rootScope:infdig] http://errors.angularjs.org/1.3.10/$rootScope/infdig?p0=10&p1=%5B%5D
at Error (native)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js:6:417
at l.$digest (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js:124:366)
at l.$apply (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js:126:471)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js:17:448
at Object.e [as invoke] (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js:37:96)
at d (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js:17:369)
at sc (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js:18:153)
at Jd (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js:16:483)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js:249:429(anonymous function) @ angular.js:11598(anonymous function) @ angular.js:8548l.$apply @ angular.js:14495(anonymous function) @ angular.js:1449e @ angular.js:4182d @ angular.js:1447sc @ angular.js:1467Jd @ angular.js:1361(anonymous function) @ angular.js:26086a @ angular.js:2741c @ angular.js:3011
angular.js:38Uncaught Error: [$rootScope:infdig] http://errors.angularjs.org/1.3.10/$rootScope/infdig?p0=10&p1=%5B%5D


My code is below:

angularApp.js

var app = angular.module('flapperNews', ['ui.router']);

app.config([
'$stateProvider',
'$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {

$stateProvider
.state('home', {
url: '/home',
templateUrl: '/home.html',
controller: 'MainCtrl',
resolve: {
postPromise: ['posts', function (posts) {
return posts.getAll();
}]
}
})
.state('posts', {
url: '/posts/:id',
templateUrl: '/posts.html',
controller: 'PostsCtrl',
resolve: {
post: ['$stateParams', 'posts', function ($stateParams, posts) {
return posts.get($stateParams.id);
}]
}
});
$urlRouterProvider.otherwise('home');
}])


app.controller('MainCtrl', [
'$scope',
'posts',
function($scope, posts){
$scope.posts = posts.posts;
$scope.title = '';
$scope.addPost = function(){
if(!$scope.title || $scope.title === '') { return;}
posts.create({
title: $scope.title,
link: $scope.link,
});
$scope.title = '';
$scope.link = '';
};
$scope.incrementUpVotes = function(post){
post.upvotes += 1;
};
}
])


app.controller('PostsCtrl', [
'$scope',
'$stateParams',
'posts',
function($scope, $stateParams, posts){
$scope.post = posts.posts[$stateParams.id];


$scope.addComment = function(){
if($scope.body === '') { return; }
$scope.post.comments.push({
body: $scope.body,
author: 'user',
upvotes: 0
});
$scope.body = '';
};


}

]);

app.factory('posts', ['$http', function(){

var o = {
posts: []
};

o.getAll = function () {
return $http.get('/posts')
.success(function (data) {
angular.copy(data, o.posts);
});
};

o.create = function (post) {
return $http.post('/posts', post)
.success(function (data) {
o.posts.push(data);
});
};

return o;
}]);


index.ejs

<html>
<head>
<title>Flapper News</title>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">

<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.10/angular-ui-router.js"></script>
<script src="/javascripts/angularApp.js"></script>
<style> .glyphicon-thumbs-up { cursor:pointer } </style>
</head>
<body ng-app="flapperNews">
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3 col-sm-6 col-sm-offset-3 col-xs-6 col-xs-offset-3">
<ui-view></ui-view>
</div>
</div>
</div>

<!-- inline Template for Home -->
<script type="text/ng-template" id="/home.html">
<div class="page-header">
<h1>Flapper News</h1>
</div>

<div ng-repeat="post in posts | orderBy:'-upvotes'">
<span class="glyphicon glyphicon-thumbs-up"
ng-click="incrementUpvotes(post)"></span>
{{post.upvotes}}
<span style="font-size:20px; margin-left:10px;">
<a ng-show="post.link" href="{{post.link}}">
{{post.title}}
</a>
<span ng-hide="post.link">
{{post.title}}
</span>
<span>
<a href = "#/posts/{{$index}}">Comments</a>
</span>
</span>
</div>

<form ng-submit="addPost()"
style="margin-top:30px;">
<h3>Add a new post</h3>

<div class="form-group">
<input type="text"
class="form-control"
placeholder="Title"
ng-model="title"></input>
</div>
<div class="form-group">
<input type="text"
class="form-control"
placeholder="Link"
ng-model="link"></input>
</div>
<button type="submit" class="btn btn-primary">Post</button>
</form>



</script>
<!-- Inline template for posts -->
<script type="text/ng-template" id="/posts.html">
<div class="page-header">
<h3>
<a ng-show="post.link" href="{{post.link}}">
{{post.title}}
</a>
<span ng-hide="post.link">
{{post.title}}
</span>
</h3>
</div>

<div ng-repeat="comment in post.comments | orderBy:'-upvotes'">
<span class="glyphicon glyphicon-thumbs-up"
ng-click="incrementUpvotes(comment)"></span>
{{comment.upvotes}} - by {{comment.author}}
<span style="font-size:20px; margin-left:10px;">
{{comment.body}}
</span>
</div>

<form ng-submit="addComment()"
style="margin-top:30px;">
<h3>Add a new comment</h3>

<div class="form-group">
<input type="text"
class="form-control"
placeholder="Comment"
ng-model="body"></input>
</div>
<button type="submit" class="btn btn-primary">Post</button>
</form>

</script>

</body>
</html>


routes - index.js

var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Post = mongoose.model('Post');
var Comment = mongoose.model('Comment');

/* GET home page. */
router.get('/', function(req, res) {
res.render('index', {title: 'Express'});
});

router.get('/posts', function(req, res, next) {
Post.find(function(err, posts){
if(err){return next(err);}

res.json(posts)
});
});

router.post('/posts', function(req, res, next) {
var post = new Post(req.body);

post.save(function(err, post){
if(err){ return next(err); }

res.json(post);
});
});

router.param('post', function(req, res, next, id){
var query = Post.findById(id);

query.exec(function(err, post){
if(err) {return next(err); }
if(!post) {return next(new Error('cant find post')); }

req.post = post;
return next();
});
});
router.get('/posts/:post', function(req, res, next){
req.post.populate('comments', function(err, post){
if(err){ return next(err);}
})
res.json(req.post)
});

router.put('/posts/:post/upvote', function(req, res, next){
req.post.upvote(function(err, post){
if(err){return next(err);}

res.json(post);
});
});

router.post('/posts/:post/comments', function(req, res, next) {
var comment = new Comment(req.body);
comment.post = req.post;

comment.post = req.post;

comment.save(function(err, comment){
if(err) { return next(err); }

req.post.comments.push(comment);
req.post.save(function(err, post) {
if(err){ return next(err);}

res.json(comment);
});
});
});

router.param('comment', function(req, res, next, id){
var query = Comment.findById(id);

query.exec(function(err, comment){
if(err) {return next(err); }
if(!comment) {return next(new Error('cant find comments')); }

req.comment = comment;
return next();
});
});

router.put('/posts/:post/comments/:comment/upvote', function(req, res, next){
req.post.upvote(function(err, post){
if(err){return next(err);}

res.json(post);
});
});

module.exports = router;

Answer

Turns out I just needed to have $http as an argument in the o.getAll function.

o.getAll = function($http) stopped the loop.

Comments