eilidh eilidh - 5 months ago 11
AngularJS Question

AngularJS Communication between ng-repeat and controller

I've just started using AngularJS, and as a project I decided to build a simple app for managing bookmarks. I want to be able to maintain a list of bookmarks and add/remove items. I'm using Django with Django REST framework, and Angular.

So far I've written a service to grab the bookmarks from the database, and I can print them to the console from my controller, but ng-repeat doesn't seem to be seeing them.

Here's my code for the service:

.factory('BookmarkService', ["$http", function ($http) {
var api_url = "/api/bookmarks/";
return {
list: function () {
return $http.get(api_url).then(function (response) {
return response.data
})
}
}
}]);


And for the controller:

.controller("ListController",
["$scope", "BookmarkService", function ($scope, BookmarkService) {
$scope.bookmarks = BookmarkService.list();
console.log($scope.bookmarks);
}]);


And here's the HTML:

<div ng-controller="ListController as listCtrl">
<md-card>
<md-card-content>
<h2>Bookmarks</h2>
<md-list>
<md-list-item ng-repeat="bookmark in listCtrl.bookmarks">
<md-item-content>
<div class="md-tile-content">
<p>{[{ bookmark.name }]} - {[{ bookmark.url }]}</p> // used interpolateProvider to allow "{[{" instead of "{{"
</div>
<md-divider ng-if="!$last"></md-divider>
</md-item-content>
</md-list-item>
</md-list>
</md-card-content>
</md-card>
</div>


When I print to the console from the controller I can see a promise object but ng-repeat isn't repeating:
image of promise object

I'd really appreciate if someone could help me to find my mistake and to understand why it is happening. I'm still not entirely comfortable with how all these parts fit together.

Thanks for your time!

Answer

There's two problems that I see with the code in question.

The first is that using the controller as syntax (ng-controller="ListController as listCtrl") requires properties to be bound to the controller instance and not to the scope if you address them using the controller name. In your case,

.controller("ListController", 
  ["BookmarkService", function (BookmarkService) {
    this.bookmarks = BookmarkService.list();
    console.log(this.bookmarks);
  }]);

The second is that you are assigning a promise to your $scope.bookmarks property. The repeater is expecting an array of objects to iterate over. You really want to assign the value resolved by the promise to $scope.bookmarks.

Instead of this

$scope.bookmarks = BookmarkService.list();

Do this

BookmarkService.list().then(function(result){
  this.bookmarks = result;
});

The final version of your controller should look something like this

.controller("ListController", 
  ["BookmarkService", function (BookmarkService) {
    this.bookmarks = BookmarkService.list();
    console.log(this.bookmarks);
  }]);