John Bliss
John Bliss

Reputation: 429

Angularjs $resource not working with an array returned from a REST API

I am trying to learn angularjs, and have hit a block in trying to databind to an array returned from a Rest API. I have a simple azure api returning an array of person objects. Service url is http://testv1.cloudapp.net/test.svc/persons.

My controller code looks like:

angular.module("ToDoApp", ["ngResource"]);
function TodoCtrl($scope, $resource) {
$scope.svc = $resource('http://testv1.cloudapp.net/test.svc/persons', {
    callback: 'JSON_CALLBACK'
}, {
    get: {
        method: 'JSONP',
        isArray: true
    }
});
$scope.items = $scope.svc.get();
$scope.msg = "Hello World";
}

My html looks like:

<html>
<head></head>
<body>
<div ng-app="ToDoApp">
    <div ng-controller="TodoCtrl">
         <h1>{{msg}}</h1>

        <table class="table table-striped table-condensed table-hover">
            <thead>
                <th>Email</th>
                <th>First Name</th>
                <th>Last Name</th>
            </thead>
            <tbody>
                <tr ng-repeat="item in items">
                    <td>{{item.Email}}</td>
                    <td>{{item.FirstName}}</td>
                    <td>{{item.LastName}}</td>
                </tr>
            </tbody>
        </table>
    </div>
</div>
</body>
</html>

Question: The table in above html is not displaying any data. I can see the call to the api in Firebug, and can also see the JSON response from the api. What am I doing incorrectly that is causing the databinding to the REST api not work?

PS:JSFiddle demonstrating this issue is at: http://jsfiddle.net/jbliss1234/FBLFK/4/

Upvotes: 14

Views: 48362

Answers (6)

Brayden Hancock
Brayden Hancock

Reputation: 796

I had similar problem and non of the answers quite worked for me, heres what i did:

    $resource("/", {}, {
       query: {
            method: 'GET',
            isArray: false,
            transformResponse: function (data, headers) {
                //if no data return so no warnings
                if (data == ''){
                    return;
                }

                return {data: $.extend({}, eval("{" + data + '}'))};
            }
        }
   });

Uses jquery. Basically convert array to object so angularjs resource doesn't poop its pants.

Upvotes: 0

Magne
Magne

Reputation: 17223

The array you get back from the server isn't a clean array, but has some extra properties. That makes ng-repeat not show anything when you iterate over it using in.

You need a special iterator to go over the array from the server, which will ignore those extra properties. So extract the array data through forEach first, like this:

$scope.items = []
var response = $scope.svc.get();
angular.forEach(response, function(item) {
  $scope.items.push(item);
});

Then you can do

<tr ng-repeat="item in items">

Upvotes: 0

Blaskovicz
Blaskovicz

Reputation: 6160

Just wanted to cross-post my adaptation of a solution Aleksander gave on another stackoverflow question: https://stackoverflow.com/a/16387288/626810:

methodName: {method:'GET', url: "/some/location/returning/array", transformResponse: function (data) {return {list: angular.fromJson(data)} }}

So when I call this function:

var tempData = ResourceName.methodName(function(){
  console.log(tempData.list); // list will be the array in the expected format
});

Obviously this a little bulky if you need to GET arrays in multiple methods / resources, but it seems to work.

Upvotes: 11

Tony Z
Tony Z

Reputation: 194

Not sure if we are having the same problem with json and REST, but this post solved my problem: array of strings not rendered correctly through angular resource

Upvotes: 0

Gwash3189
Gwash3189

Reputation: 333

In order to handle arrays with the $resource service, it's suggested that you use the query method. As you can see below, the query method is built to handle arrays.

{ 'get':    {method:'GET'},
  'save':   {method:'POST'},
  'query':  {method:'GET', isArray:true},
  'remove': {method:'DELETE'},
  'delete': {method:'DELETE'} };

The code you should use in order to return this array to your scope is

angular.module("ToDoApp", ["ngResource"]);

function TodoCtrl($scope, $resource) {
    var svc = $resource('http://testv1.cloudapp.net/test.svc/persons');
    $scope.items = svc.query();
    $scope.msg = "Hello World";
}

This assumes that your REST API is working and will return an array.

For further reading head to the docs

http://docs.angularjs.org/api/ngResource.$resource

Upvotes: 29

Fanda
Fanda

Reputation: 3786

Use isArray param, if you have nested objects:

angular.module('privilegeService', ['ngResource']).
factory('Privilege', function ($resource) {
    return $resource('api/users/:userId/privileges', 
                     {userId: '@id'}, 
                     {'query':  {method:'GET', isArray:false}});
});

Than you can use container.object.property notation to access objects and its properties.

Upvotes: 7

Related Questions