7

I am returning a array of objects from the server:

[{id: 1, name: "name"},{id: 2, name: "name2"}]

Now I use angular-resource $query to fetch the data as it expects an array. When the data is received I get this error:

TypeError: value.push is not a function

Is there an issue with the response I give from server=?

Source of error:

 // jshint +W018
                if (action.isArray) {
                  value.length = 0;
                  forEach(data, function(item) {
                    if (typeof item === "object") {
                      value.push(new Resource(item));
                    } else {
                      // Valid JSON values may be string literals, and these should not be converted
                      // into objects. These items will not have access to the Resource prototype
                      // methods, but unfortunately there
                      value.push(item);
                    }
                  });
                } else {
                  shallowClearAndCopy(data, value);
                  value.$promise = promise;
                }
              }

Controller:

var stream = [];
stream = new VideoStream({param: 'streamTypes'});
stream.$query();

Service:

app.service('DataService', [
    '$resource', 'Common', '$rootScope',
    function($resource, Common, $rootScope) {
        return $resource($rootScope.appWebRoot + "myUrl/:param", {param: '@param'},
        {

        });
    }
]);

enter image description here enter image description here enter image description here

VideoStream:

app.service('VideoStream', [
    '$resource', 'Common', '$rootScope',
    function($resource, Common, $rootScope) {
        return $resource($rootScope.appWebRoot + "videoStreams/api/:param",
        {param: '@param'},
        {

        });
    }
]);
Kaspar
  • 1,600
  • 4
  • 24
  • 46
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/83452/discussion-between-grundy-and-kaspar). – Grundy Jul 16 '15 at 16:07

2 Answers2

9

The problem you have is that you are creating an instance of your resource as an object

var stream = [];
stream = new VideoStream({param: 'streamTypes'}); //This is the problem. $resource is expecting an array.
stream.$query(); //This is an instance method.

//All you need to do is:
var stream = [];
stream = VideoStream({param: 'streamTypes'}).query();

From https://docs.angularjs.org/api/ngResource/service/$resource:

$resource returns:

A resource "class" object with methods for the default set of resource actions optionally extended with custom actions. The default set contains these actions:

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

Calling these methods invoke an $http with the specified http method, destination and parameters. When the data is returned from the server then the object is an instance of the resource class. The actions save, remove and delete are available on it as methods with the $ prefix

Wawy
  • 6,259
  • 2
  • 23
  • 23
  • Was this caused because I use .service instead of .factory? – Kaspar Jul 16 '15 at 18:19
  • 1
    @Kaspar, nope, seems this because instance can be mapped only to one object – Grundy Jul 16 '15 at 18:29
  • 2
    The way $resource works is that when you define a $resource it returns a class with some class methods such as query and get. Calling those methods will create a new instance of your class. You don't need to `new` your class unless you have existing data that you want to transform into a resource class. More info at https://docs.angularjs.org/api/ngResource/service/$resource – Wawy Jul 16 '15 at 18:42
  • Thank you for the info! Technically Grundy answered first with a solution that solved my problem. So Grundy, if you write a answer I can accept it, if you don't want to then I will accept Wawy,s answer. – Kaspar Jul 16 '15 at 19:11
  • @Kaspar, it was a simple guess :-) i think Wawy should add in answer some explaining from comments and docs, and you can accept it :-) – Grundy Jul 17 '15 at 06:32
1

In addition to Wawy's answer, according to the docs here:

The action methods on the class object or instance object can be invoked with the following parameters:

  • HTTP GET "class" actions: Resource.action([parameters], [success], error])
  • non-GET "class" actions: Resource.action([parameters], postData, [success], [error])
  • non-GET instance actions: instance.$action([parameters], [success], [error])

On checking the value of VideoStream in the controller, we find:

function Resource(value) {
      shallowClearAndCopy(value || {}, this);
    } // Actual Resource class object with regular action(s) we can work with

there

Calling VideoStream({param: 'streamTypes'}) returns:

undefined // Cannot call anything of undefined

and new VideoStream({param:'streamTypes'}) returns:

Resource {param: "streamTypes"}
// Instance of the Resource class (an object) where $action(s) are available
// Verified in the chrome console

With this in mind, the case should be:

var stream = [];
stream = VideoStream.query({param: 'streamTypes'});
Community
  • 1
  • 1
NateNjugush
  • 61
  • 1
  • 4