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/

6 Answers 6

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

Sign up to request clarification or add additional context in comments.

Comments

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.

1 Comment

transformResponse: function (data, headers) { return { count: angular.fromJson(data) } } // works perfect for me. Thanks!
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.

1 Comment

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
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

Comments

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">

Comments

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.

1 Comment

Sorry eval to parse JSON ? Please don't! Use JSON.parse!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.