5

How to make angularjs $resource return an array of objects derived/prototyped from specified domain object?

Here is an example on http://plnkr.co/edit/AVLQItPIfoLwsgDzoBdK?p=preview that processes a set of Notes objects.

app.controller('MainCtrl', function($scope, NoteResource) {
$scope.name = 'World';
$scope.notes  = NoteResource.query();

$scope.spellCheckAllNotes = function() {
  angular.forEach($scope.notes, function(note) {
    note.spellCheck();
   });
 }
});

The issue is that $resource returns array of Resources and not an array of Notes with Resource methods added to prototypes.

[solution shall follow "good" javascript practices]

okigan
  • 1,559
  • 2
  • 18
  • 33

2 Answers2

10

Here is the completed plunker. Yes raw json is parsed to JSON object. It is using transformResponse as mentioned by Armando.

app.factory('NoteResource', ['$resource',
  function($resource) {
    var res =  $resource('http://okigan.apiary.io/notes/:id', {}, {
      query: {
        method: 'GET',
        params: {
        },
        isArray: true,
        transformResponse: function(data, header){
          //Getting string data in response
          var jsonData = JSON.parse(data); //or angular.fromJson(data)
          var notes = [];

          angular.forEach(jsonData, function(item){
            var note = new Note();
            note.noteTitle = item.title;  
            notes.push(note);
          });

          return notes;
        }
      }
    });
    return res;
  }
]);

Just to show title is not used from the raw resource, I modified title to noteTitle in Note and in html.

dmahapatro
  • 49,365
  • 7
  • 88
  • 117
  • 1
    for the JSON parsing, you can stick with the Angular framework by using var jsonData = angular.fromJson(data); – Spencer May 07 '14 at 17:51
  • Yes definitely an option, updated accordingly, thanks. @Spencer – dmahapatro May 07 '14 at 17:53
  • 1
    btw, I used angular.extend() which automates the process even more – okigan May 07 '14 at 18:07
  • Does this still work with later AngularJS versions. For me it's still a series of Resource objects and a couple of others like $promise and resolve. – sathishvj Mar 06 '15 at 20:08
  • Yes it does. I am using the same principle in v1.3.13 @sathishvj – dmahapatro Mar 06 '15 at 20:31
  • The notes object for me inside the transformResponse is an array of objects as we'd want, but it's almost like the value is not getting returned. Outside of it, it is still the same series of resource objects and $promise and resolve. Any indication to what could be going wrong? – sathishvj Mar 07 '15 at 03:15
  • I created a new plnk for it: http://plnkr.co/edit/9ZG7sLe7ZpQXKkNbZbSI. I'm still seeing the old behavior. Maybe I should raise a separate question. – sathishvj Mar 07 '15 at 03:49
  • it's not that much good, once the service returns, it will change objects type to resource, not note... i have same issue... it introduce bugs with ts interface and object types... – Hassan Faghihi Apr 06 '16 at 05:45
1

You can manipulate your data using transformResponse option in your resource service definition (make sure to set isArray to true):

angular.module('services', ['ngResource']).
    factory("yourService", function ($resource) {
        return $resource(
            '/custom/url', {}, {
            get: {
                method: 'GET',
                isArray: true,
                transformResponse: function(data, headers){
                    //
                    // transform to array of objects 
                    return data;
                }
            }
        }
    );
});
Spencer
  • 2,245
  • 3
  • 28
  • 50
  • data seems to be raw json, not objects -- please complete the solution (in plunker the button will show message box) – okigan May 07 '14 at 17:41
  • In the comments it says: "transform to array of objects" you need to add your own logic. –  May 07 '14 at 18:52