Search code examples
javascriptangularjsngresource

Angular - ngResource breaks data binding


I am new to Angular, and am trying to get up to speed with ngResource.

I created a factory in my chapter.service.js file

angular.module('myApp')
.factory('Chapter', function ($resource) {
  return $resource('/api/book/chapter/:id'); // Note the full endpoint address
});

matchescontroller.js

angular.module('myApp').controller('matchesCtrl', function($scope, $location, Chapter) {

// This is used to get URL parameters

$scope.url = $location.path();
$scope.paths = $scope.url.split('/');
$scope.id = $scope.paths[2];
$scope.action = $scope.paths[3];

//Trying to call the test data
    var chapters = Chapter.query();

    $scope.myFunction = function() {
        alert(chapters.length);
    }

My view where I test the function

<button ng-click="myFunction()">Click Here</button>

I created a test function to test whether my query returned any results. When I click on the button, I'm alerted with 0, which means the query didn't work.

When I change the function to

$scope.myFunction = function() {
    console.log(Object.keys(chapters));
}

I get [$promise, $resolve], but none of the Schema keys

I must be doing something wrong, but I was looking at this tutorial

http://www.masnun.com/2013/08/28/rest-access-in-angularjs-using-ngresource.html

Any help will be appreciated.

Edit: Here is the response I got from the server

GET http://localhost:9000/api/book/chapter/1 500 (Internal Server Error)

Solution

  • $scope.myFunction = function() {
        Chapter.query({}, function(data) {
            $scope.chapters = data;
        }, function(error) {
            // custom error code
        });
    }
    

    When working with $resource I prefer to use the success/error handlers that the API comes with as opposed to dealing the promise directly. The important thing to realize is that just because you called query does not mean that the result is immediately available. Thus the use of a callback that handles success/error depending on what your backend returns. Only then can you bind and update the reuslt in the UI.

    Also, while we're talking about it I notice that you didn't wire up the optional paramter in your $resouce URL. $resource takes a second paramter which is an object that supplies mapping for the /:id part of your route.

    return $resource('/api/book/chapter/:id', {id: '@id'});
    

    What this notation means is that you pass an object to $resource that has a property called id, it will be subbed into your URL.

    So this:

    $scope.item = {id: 42, someProp: "something"};
    
    Chapter.get({$scope.item}....
    

    Will result in an API call that looks like '/api/book/chapter/42'