Reputation: 9806
I'm following this tutorial When I try to post a comment on a post I get a TypeError: Cannot read property 'comments' of undefined
error in my console.
the mainCtrl,
.controller('mainCtrl', ['$scope', 'posts',
function($scope, posts){
$scope.posts = posts.posts;
$scope.addPost = function(){
if(!$scope.title || $scope.title === '') { alert("Field can't left blank"); return; }
$scope.posts.push({
title: $scope.title,
upvotes: 0,
comments: [
{author: 'Joe', body: 'Cool post!', upvotes: 0},
{author: 'Bob', body: 'Great idea but everything is wrong!', upvotes: 0}
]
});
};
}
])
and the postCtrl,
.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 = '';
};
}
])
Both controllers are in mainCtrl.js
.
And here are my home.html and post.html partials which are being included through router-ui.
%script{:id => "/home.html", :type => "text/ng-template"}
%h1
Flappernews
%a{:href => "#/posts/{{$index}}"} Comments
%script{:id => "/posts.html", :type => "text/ng-template"}
%h2
Below here should be comments
%span
{{ post.comments }}
%div{"ng-repeat" => "comment in post.comments | orderBy:'-upvotes'"}
{{comment.upvotes}} - by {{comment.author}}
%span{:style => "font-size:20px; margin-left:10px;"}
{{comment.body}}
%form{"ng-submit" => "addComment()"}
%h3 Add a new comment
.form-group
%input.form-control{"ng-model" => "body", :placeholder => "Comment", :type => "text"}
%button.btn.btn-primary{:type => "submit"} Post
When I visit the homepage I get redirected to localhost:3000/#/home
I can then enter a title and post it. When I click on the comments
link I get redirected to http://localhost:3000/#/posts/
and when I try to post a comment I get the
TypeError: Cannot read property 'comments' of undefined
at Scope.$scope.addComment
error.
Upvotes: 6
Views: 6459
Reputation: 835
You have defined two separate controllers, don't need to do that. If you look at that tutorial again you will see that addPost and addComment functions are inside single controller like this
.controller('PostsCtrl', [
'$scope',
'$stateParams',
'posts',
function($scope, $stateParams, posts){
// Fetch post object from state parameter.
$scope.post = posts.posts[$stateParams.id];
// Add Post.
$scope.posts.push({
title: $scope.title,
link: $scope.link,
upvotes: 0,
comments: [
{author: 'Joe', body: 'Cool post!', upvotes: 0},
{author: 'Bob', body: 'Great idea but everything is wrong!', upvotes: 0}
]
});
// Add comment.
$scope.addComment = function(){
if($scope.body === '') { return; }
$scope.post.comments.push({
body: $scope.body,
author: 'user',
upvotes: 0
});
$scope.body = '';
};
}]);
add post and comment works on single Post object where comments property is pre defined.
Upvotes: 1
Reputation: 12749
Since I cannot debug the code so I'll try to list all possible reasons and you can confirm which is true for your case
posts
service correctly.Place a breakpoint after the $scope.posts.push
and log posts.posts
to make sure the new object is added to the array
Make sure the PostsCtrl
has the same posts.posts
array with the new post added.
Make sure $stateParams.id
is actually a valid index for the posts.posts
array
I hope this helps. If not, make a comment with the results.
Upvotes: 0
Reputation: 1118
In your 'mainCrtl', you are not saving/adding new post data to your 'posts' object but added to '$scope.posts' so its reflecting in your page with comment link (let's say your newly created post id is 'x' ).
And when you are clicking on comments link, and trying to check the data which is not added before to your 'posts' object ie.., posts[x] is undefined (you have not added id 'x' data in maincrtl).
Hope I have Answered your question.
Upvotes: 0
Reputation: 883
I am sure there is reference link issue. $scope.posts = posts.posts; only should be used to access the posts object. CURD operation should be performed on service directly.
$scope.posts would get automatically changed because there is a reference link between $scope.posts and posts.
Please make below change. Hope it should work.
$scope.addPost = function () {
if (!$scope.title || $scope.title === '') {
alert("Field can't left blank");
return;
}
posts.posts.push({
title: $scope.title,
upvotes: 0,
comments: [{
author: 'Joe',
body: 'Cool post!',
upvotes: 0
}, {
author: 'Bob',
body: 'Great idea but everything is wrong!',
upvotes: 0
}]
});
};
now you are able to share data between different controllers. Same should be done while adding comment.
Important part :
you can not get post like posts.posts[$stateParams.id]; This will match the index of array and return the object.
angular.forEach(posts.posts, function (post) {
if (post.id === parseInt($stateParams.id)) {
$scope.post = post;
return;
}
})
Hope this will help you.
Upvotes: 0