title: AngularJS and complex JSON returned by django tastypie
body: <p>I have few resources written on AngularJS that access a Tastypie API. Everything works fine, except for a detail: tastypie always encapsulate the actual result inside a <code>objects</code> attribute on a JSON, example:</p>
  
  <p><code>/api/v1/reminder/</code>:</p>
  
  <pre><code>{
      meta: {
          limit: 20,
          next: null,
          offset: 0,
          previous: null,
          total_count: 3
      },
      objects: [{
          category: {
              color: "#999999",
              id: 1,
              name: "Groceries",
              resource_uri: "/api/v1/category/1"
          },
          description: "",
          due_date: "2010-10-16",
          id: 1,
          repeat: "weekly",
          resource_uri: "/api/v1/reminder/1",
          value: "-50"
      }, {
          category: {
              color: "#999999",
              id: 1,
              name: "Groceries",
              resource_uri: "/api/v1/category/1"
          },
          description: "",
          due_date: "2010-10-17",
          id: 2,
          repeat: "weekly",
          resource_uri: "/api/v1/reminder/2",
          value: "-50"
      }
  }
  </code></pre>
  
  <p>It was wasy to fix using a callback to the <code>get()</code> call:</p>
  
  <pre><code>Reminder.get().$then(function (result) {
      $scope.reminders  = result.data.objects;
  });
  </code></pre>
  
  <p>But I know <code>result.resource</code> is an actual <code>Reminder</code> instance.</p>
  
  <pre><code>.factory('Reminder', ['$resource', function($resource){
      var Reminder = $resource('/api/v1/reminder/:id', {}, {
          get: {
              method: 'GET',
              isArray: false
          }
      });
  
      Reminder.prototype.TESTE = function () {console.log('asd');};
  
      return Reminder;
  }])
  </code></pre>
  
  <p>Now I need to implement behavior on my <code>Reminder</code> class, and I need every element on my <code>meta.objects</code> to be an instance of <code>Reminder</code>:</p>
  
  <pre><code>Reminder.get().$then(function (result) {
      $scope.reminders  = result.data.objects;
  
      result.resource.TESTE(); // -&gt; outputs 'asd'
  
      o = result.data.objects[0];
      o.TESTE // -&gt; undefined, obvisously
      i = new Reminder(o);
      i.TESTE() // -&gt; outputs 'asd'
  });
  </code></pre>
  
  <p>So, how to I get angularjs to understand that every object on <code>objects</code> is the actual result so it behaves like a list of instances?</p>
  
  <p>The workaround is to creating a new list iterating on the results creating the instances, but it's not optimal...</p>
  
  <p>Suggestions?</p>
  
  <h1>Solution by @rtcherry:</h1>
  
  <p>As suggested by rtcherry, I used <a href="https://github.com/mgonto/restangular" rel="noreferrer">restangular</a></p>
  
  <p>Configuring the reading of request data:</p>
  
  <pre><code>.config(['RestangularProvider', function(RestangularProvider) {
      RestangularProvider.setBaseUrl("/api/v1");
  
      RestangularProvider.setResponseExtractor(function(response, operation, what, url) {
          var newResponse;
          if (operation === "getList") {
              newResponse = response.objects;
              newResponse.metadata = response.meta;
          } else {
              newResponse = response.data;
          }
          return newResponse;
      });
  }])
  </code></pre>
  
  <p>Loading the reminders:</p>
  
  <pre><code>function RemindersCtrl ($scope, $rootScope, Reminder) {
      $scope.reminders = Reminder.getList();
  }
  </code></pre>
  
  <p>Adding my custom method to <code>Reminder</code> (not as clean as ngResource, but doable):</p>
  
  <pre><code>.factory('Reminder', ['Restangular', '$filter', function(Restangular, $filter){
      var Reminder = Restangular.all('reminder');
  
      var remainingDays = function () {
          //do stuff
      };
  
      // adding custom behavior
      Restangular.addElementTransformer('reminder', false, function (reminder) {
          reminder.remainingDays = remainingDays;
          return reminder;
      });
  
      return Reminder;
  }])
  </code></pre>
  
  <h1>Solution by @moderndegree:</h1>
  
  <p>I used pure <code>ngResource</code>:</p>
  
  <pre><code>var tastypieDataTransformer = function ($http) {
      return $http.defaults.transformResponse.concat([
          function (data, headersGetter) {
              var result = data.objects;
              result.meta = data.meta;
              return result;
          }
      ])
  };
  
  ...
  
  .factory('Reminder', ['$resource', '$http', function($resource, $http){
      var Reminder = $resource('/api/v1/reminder/:id', {}, {
          query: {
              method: 'GET',
              isArray: true,
              transformResponse: tastypieDataTransformer($http)
          }
      });
  
      Reminder.prototype.remainingDays = function () {
          // doing stuff
      };
  
      return Reminder;
  }])
  </code></pre>
  
  <p>My controller:</p>
  
  <pre><code>Transaction.query(filter).$then(function (result) {
      $scope.days = [];
      var transactions = result.resource;
      resource[0].remainingDays(); // it works
  
  });
  </code></pre>