5

When trying to poll a custom method copies on an AngularJS Resource I get the following error at angular.js:10033: (The method copy works just fine.)

TypeError: undefined is not a function
at https://code.angularjs.org/1.3.0-beta.8/angular-resource.min.js:9:347
at Array.forEach (native)
at q (https://code.angularjs.org/1.3.0-beta.8/angular.min.js:7:280)
at q.then.p.$resolved (https://code.angularjs.org/1.3.0-beta.8/angular-resource.min.js:9:329)
at J (https://code.angularjs.org/1.3.0-beta.8/angular.min.js:101:5)
at J (https://code.angularjs.org/1.3.0-beta.8/angular.min.js:101:5)
at https://code.angularjs.org/1.3.0-beta.8/angular.min.js:102:173
at g.$eval (https://code.angularjs.org/1.3.0-beta.8/angular.min.js:113:138)
at g.$digest (https://code.angularjs.org/1.3.0-beta.8/angular.min.js:110:215)
at g.$apply (https://code.angularjs.org/1.3.0-beta.8/angular.min.js:113:468)

Angular.js 10016 - 10035:

function consoleLog(type) {
  var console = $window.console || {},
      logFn = console[type] || console.log || noop,
      hasApply = false;

  // Note: reading logFn.apply throws an error in IE11 in IE8 document mode.
  // The reason behind this is that console.log has type "object" in IE8...
  try {
    hasApply = !!logFn.apply;
  } catch (e) {}

  if (hasApply) {
    return function() {
      var args = [];
      forEach(arguments, function(arg) {
        args.push(formatError(arg));
      });
      return logFn.apply(console, args); // This is line 10033 where the error gets thrown.
    };
  }

Simplified resource:

angular.module('vgm.content-pages')
.factory('ContentPage', function($resource, $http) {

  return $resource('/api/content-page/:id', { id:'@page.id' }, {
    copy: {
      method: 'POST',
      url: '/api/content-page/copy/:id'
    },
    copies: {
      method: 'GET',
      isArray: true,
      url: '/api/content-page/copies/:id'
    }
  });

});

Simplified directive where I'm getting the error:

angular.module('vgm.genericForms')
.directive('vgmFormCopyPicker', function() {

  return {
    restrict: 'E',
    replace: true,
    templateUrl: '/static/common/generic-forms/widgets/view-copy-picker.html',
    scope: {
      resource: '=',
    },
    controller: function($scope, $element) {

      $scope.pages = [];

      $scope.loadCopies = function() {

        $scope.resource.$copies()
          .then(function(response) {
            $scope.pages = response.data;
          });

      };

    }
  };

});

As soon as I run the loadCopies method, executing the line $scope.resource.$copies() throws the error above.

In the Chrome Inspector I see the call to my API is actually being done. But resolving the promise seems to throw some error...

How can I solve this error?

EDIT:

$scope.resource = ContentPage.get({id: $stateParams.id}).$promise
$scope.resource.$save() // Works
$scope.resource.$update() // Works
$scope.resource.$copy() // Works
$scope.resource.$copies() // Does not work!

Angular Resource is trying to overwrite my initial resource with an array of items. But the instance of Resource does not have a method push of course.

0

3 Answers 3

8

I found the answer:

A resource is supposed to represent the matched data object for the rest of its lifespan. If you want to fetch new data you should do so with a new object.

$scope.copies = ContentPage.copies()
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Guido. I had this same problem. I think the docs are a bit confusing. If I'm understanding it correctly, you can't call an instance method which has isArray:true on a /single/ resource instance because the single instance is not an array.
That's correct. And it makes sense if you think about it: first the property represents a list of items, and suddenly it represents a single item, that's not consistent.
6

The answer from Guido is correct but I didn't get it at the first time.

If you add a custom method to your Angular $resource and using isArray: true and expecting to get an Array of something from your WebService you probably want to store the response in an Array.

Therefore you shouldn't use the instance method like this:

var ap = new Ansprechpartner();
$scope.nameDuplicates = ap.$searchByName(...);

But use the resource directly:

$scope.nameDuplicates = Ansprechpartner.searchByName(...)

Using following Angular resource:

mod.factory('Ansprechpartner', ['$resource',
    function ($resource) {
        return $resource('/api/Ansprechpartner/:id', 
            { id: '@ID' },
            {
                "update": { method: "PUT" },
                "searchByName": { method: "GET", url: "/api/Ansprechpartner/searchByName/:name", isArray: true }
            }
        );
    }
]);

Comments

-1

I am using Mean.js and this plagued for a few hours. There is a built in $update but it was not working when I tried to apply it to an object returned by a $resource. In order to make it work I had to change how I was calling the resource to update it.

For example, with a Student module, I was returning it with a $resource into $scope.student. When I tried to update student.$update was returning this error. By modifying the call to be Students.update() it fixed the problem.

 $scope.update = function() {
   var student = $scope.student;
   var result = Students.update(student);

   if(result){
      $scope.message = 'Success';
   } else {
      $scope.error = 
        'Sorry, something went wrong.';
   }
 };

Comments

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.