14

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/

John Bliss
  • 429
  • 2
  • 5
  • 12

6 Answers6

29

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

Gwash3189
  • 333
  • 3
  • 8
11

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.

Community
  • 1
  • 1
Blaskovicz
  • 6,122
  • 7
  • 41
  • 50
  • transformResponse: function (data, headers) { return { count: angular.fromJson(data) } } // works perfect for me. Thanks! – Peter.Wang Jun 26 '16 at 00:29
7

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.

Fanda
  • 3,760
  • 5
  • 37
  • 56
  • The isArray param is already there. Setting it to true or false has no effect in this case. Can you please take a look at the jsfiddle and advise what exactly needs to be done to get the data bound. Thanks – John Bliss Mar 31 '13 at 15:58
0

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

Community
  • 1
  • 1
Tony Z
  • 195
  • 1
  • 8
0

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">
Magne
  • 16,401
  • 10
  • 68
  • 88
0

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.

Brayden Hancock
  • 786
  • 1
  • 6
  • 22