2

I have a simple RESTful API set up using Django Rest Framework and I'm trying to use AngularJS to consume it. I've read about controllers and resources in angular and I'm following multiple tutorials, but for some reason in my template I can't seem to access the JSON properly.

app.js

var blogApp = angular.module('blogApp', ['ngResource']);

blogApp.factory('Post', ['$resource', function($resource) {
    return $resource('/api/posts/:slug/', { slug:'@slug'});
}]);

blogApp.controller('postController', ['$scope', 'Post', function($scope, Post) {
    $scope.posts = []

    Post.query().$promise.then(function(posts) {
        $scope.posts = posts;
        for (key in posts){
            console.log(posts[key]);
        }
    });
}]);

index.html ****EDIT**** I added the filter here to test, and it does do the filtering as intended, but still no text shows up in the <div>'s

<div class="container">
   <div class="col-sm-10">

      <div ng-controller="postController">
         <input type="text" ng-model="textTest">

         <div class="well" ng-repeat="(key, post) in posts | filter: textTest">
            <h1>{{ post.title }}</h1>
            {{ post.content }}
         </div>
      </div>

   </div>
</div>

This is what is returned if I do a GET on /api/posts/

[
    {
        "url": "http://localhost:8000/api/posts/i-had-a-api-his-name-was-bingo/",
        "id": 0,
        "title": "I had a api... his name was Bingo",
        "content": "E-I-E-I-O",
        "owner": "Heather",
        "comments": "http://localhost:8000/api/posts/i-had-a-api-his-name-was-bingo/comments/"
    },
    {
        "url": "http://localhost:8000/api/posts/if-i-could-show-you-the-world/",
        "id": 1,
        "title": "If I Could Show You The World",
        "content": "It would be shining, and shimmering",
        "owner": "Heather",
        "comments": "http://localhost:8000/api/posts/if-i-could-show-you-the-world/comments/"
    },
    ...
]

In the template, all that shows up is a blank grey box (because of the bootstrap class) with no title or content from the posts, but the proper number of boxes do show up for the number of post objects. What am I missing?

EDIT: the console shows no errors, and the GET request is returning 200 application/json. I have a console.log($scope.posts) which is printing out [Resource, Resource, Resource, Resource, Resource, Resource, Resource, $promise: Object, $resolved: true]. Also,

for (key in $scope.posts){
   console.log(posts[key]);
}

prints out

Resource {url: "http://localhost:8000/api/posts/i-had-a-api-his-name-was-bingo/", id: 0, title: "I had a api... his name was Bingo", content: "E-I-E-I-O", owner: "Heather"…}
wazoox
  • 1,384
  • 16
  • 27
Tyler Dovall
  • 130
  • 2
  • 11

3 Answers3

2

The answer was frustratingly simple. Because I'm using django-rest-framework for my API, and django by default uses double curly braces for it's variables, it was getting confused. I just had to change the delimiter.

var blogApp = angular.module('blogApp', ['ngResource'], function($interpolateProvider) {
    $interpolateProvider.startSymbol('[[');
     $interpolateProvider.endSymbol(']]');
});

then in my templates use '[[ ]]' for angular variables. (ex. [[ post.title ]])

Tyler Dovall
  • 130
  • 2
  • 11
0

You need to put $scope.$apply() since this is an asynchronous call

lastboy
  • 566
  • 4
  • 12
  • Do I add this at the end of the controller? – Tyler Dovall Sep 04 '14 at 06:43
  • Add it where the data is being retrieved. This command is about updating the scope. when the scope property is updated you need to apply it to the scope. Put it in the promise after the request retrieved successfully and you set the scope property with the new data – lastboy Sep 04 '14 at 06:59
  • It doesn't help, it just introduces a $rootScope error. Angular says the action is already in progress. – Tyler Dovall Sep 04 '14 at 07:20
  • It looks like you need to add $settimeout look at this article http://www.bilalquadri.com/blog/2014/05/18/understanding-promises-in-angular/ – lastboy Sep 04 '14 at 07:45
  • According to that blog, $http wraps $apply so it's not needed, and $resource is a wrapper for $http. So this shouldn't be necessary right? – Tyler Dovall Sep 04 '14 at 15:35
  • Well yes and no, you need to update the scope, but in a certain way.. You should use timeout. The answer is in this link. http://stackoverflow.com/questions/12729122/prevent-error-digest-already-in-progress-when-calling-scope-apply – lastboy Sep 04 '14 at 19:07
0

This will probably work.

blogApp.controller('postController', ['$scope', 'Post', function($scope, Post) {
    $scope.posts = []

    Post.query().$promise.then(function(posts) {
        $scope.posts = posts;
        $scope.$apply();
    });
}]);
CodePrimate
  • 6,646
  • 13
  • 48
  • 86
  • When I add the apply in I get $rootScope error from angular. It says it's already in progress. In short, it doesn't fix my problem. – Tyler Dovall Sep 04 '14 at 07:19