Gabriel Rayzal
Gabriel Rayzal

Reputation: 43

AngularJS, ng-repeat doesn't repeat

I'm new in AngularJs and I'm facing a problem with ng-repeat. Basically, I want to get the comments relative to an article from my database with ajax, then to display them with ng-repeat. I then have an array in which I push my comments. My problem is that when I manually create a comment in my array, it works well, but if I push automatically this comment from the callback of my ajax function, the array is updated, but not my view.

View in html :

var articleApp = angular.module('articleApp', []);
articleApp.controller('CommentsController', function CommentsController($scope) {
    $scope.comments = [];
    // This push works well, my view is updated
    $scope.comments.push({
        content: "Hello world !",
        date: "2 minutes ago",
        id: 29,
        author: {
            pseudo: "Sean"
        }
    });
    // When I push with this function, my array is updated, but not the view
    $scope.addComment = function(comment) {
        $scope.comments.push({
            content: comment.comment,
            id: comment.id,
            date: comment.date_post,
            author: {
                id: comment.author.id,
                pseudo: comment.author.pseudo
            }
        });
    };
    var articleID = document.getElementById('articleID').textContent;
    // getComments is defined elsewhere, and returns the 20 first comments
    getComments(20, articleID, 0, function(comments) {
        for(var i = 0; i < comments.length; i++) {
            $scope.addComment(comments[i]);
        }
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<section id="commentsSection" class="bottom_apps" ng-controller="CommentsController as comments">
  <article id = "{{comment.id}}" class="comment_container" ng-repeat="comment in comments">
    <div class="comment_header">
      <span class="comment_author">{{comment.author.pseudo}}</span>
      <span class="comment_date">{{comment.date}}</span>
    </div>
    <div class="comment_content">
      {{comment.content}}
    </div>
  </article>
</section>

I double-checked, triple-checked all my code, but I can't see where I did a mistake.

Upvotes: 1

Views: 78

Answers (2)

Immanuel Kirubaharan
Immanuel Kirubaharan

Reputation: 1104

You can try doing something like below code, Also please check this plunker link for your given example scenario with some dummy action.

Controller:

$scope.comments = [];
    $scope.comment={};
    // This push works well, my view is updated
    $scope.comments.push({
        content: "Hello world !",
        date: "2 minutes ago",
        id: 29,
        author: {
            pseudo: "Sean"
        }
    });
    $scope.comments.push({
        content: "Hello world 2!",
        date: "5 minutes ago",
        id: 30,
        author: {
            pseudo: "Jack"
        }
    });
    // When I push with this function, my array is updated, but not the view
    $scope.addComment = function() {
        $scope.comments.push({
            content: $scope.comment.comment,
            id: $scope.comments.length+1,
            date: new Date(),
            author: {
                id: $scope.comments.length+1,
                pseudo: $scope.comment.comment
            }
        });
        console.log($scope.comments);
    };

Template:

<section id="commentsSection" class="bottom_apps" ng-controller="CommentsController">
      <input type="text" ng-model="comment.comment"/>
      <button type="button" ng-click="addComment()">Add Comment</button><br/>
      <article id = "{{comment.id}}" class="comment_container" ng-repeat="comment in comments">
        <div class="comment_header">
          <span class="comment_author">{{comment.author.pseudo}}</span>
          <span class="comment_date">{{comment.date}}</span>
        </div>
        <div class="comment_content">
          {{comment.content}}
        </div>
      </article>
    </section>

Upvotes: 0

Pedro A
Pedro A

Reputation: 4333

Looks like your getComments works asynchronously, since you are passing a callback function which has the comments as a parameter.

Therefore, even though you update your comments inside that callback, AngularJS does not seem to "notice it", right?

This is because you have to tell AngularJS explicitly to run a new digest cycle.

In short, just add $scope.$apply() to the end of your callback:

getComments(20, articleID, 0, function(comments) {
    for(var i = 0; i < comments.length; i++) {
        $scope.addComment(comments[i]);
    }
    $scope.$apply();
});

To learn more about this, search for "AngularJS digest cycle". In short, the thing is: AngularJS updates everything in what are called digest cycles. If a digest cycle does not happen, AngularJS will not "notice" the changes. When things runs synchronously, AngularJS automatically runs digest cycles. But for many asynchronous things, AngularJS can't figure it out automatically, so you have to tell AngularJS explicitly to perform a digest cycle.

Upvotes: 1

Related Questions