6

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.

8
  • In the mainCtrl you have $scope.posts. and in the mainCtrl you have $scope.post. Could you try to rename $scope.post. to $scope.posts. and see if that works? Commented Aug 12, 2015 at 11:39
  • See what is returned by posts.posts[$stateParams.id]; - add console.log($scope.post); to have a quick look. Commented Aug 12, 2015 at 11:56
  • Chaing $scope.post tot $scope.posts didn't change anything. And I've added console.log($scope.post just beneath the $scope.post = posts.posts[$stateParams.id]; line and I'm getting a undefined output in the console. Commented Aug 12, 2015 at 12:02
  • So is $stateParams.id returning the correct id? Commented Aug 12, 2015 at 12:10
  • 1
    @Peter I can't see how you're setting the id on $stateparams but this is where you need to look. Commented Aug 12, 2015 at 12:25

4 Answers 4

1
+100

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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.

1 Comment

In the end the problem was the link to the comment pages. It was in the wrong section of the page. Fixed now. Thanks for the help though.
0

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.

Comments

0

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

  1. Make sure the new post is pushed to the 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

  1. Make sure the PostsCtrl has the same posts.posts array with the new post added.

  2. 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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.