2013-06-26 24 views
10

Bir Tastypie API'sine erişen AngularJS üzerine yazılmış birkaç kaynağım var. Her şey bir ayrıntı dışında çalışıyor:AngularJS ve karmaşık JSON django tastypie tarafından döndürülen

/api/v1/reminder/: tastypie hep bir JSON, örneğin bir objects özniteliği içindeki fiili sonucu encapsulate

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

O get() çağrısına bir geri arama kullanarak düzeltmek için wasy oldu :

Reminder.get().$then(function (result) { 
    $scope.reminders = result.data.objects; 
}); 

Ama result.resource gerçek Reminder örneğidir biliyorum.

.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; 
}]) 

Şimdi benim Reminder sınıfı davranışı uygulamak gerekir ve ben Reminder bir örneği olmak benim meta.objects her eleman gerekir:

Reminder.get().$then(function (result) { 
    $scope.reminders = result.data.objects; 

    result.resource.TESTE(); // -> outputs 'asd' 

    o = result.data.objects[0]; 
    o.TESTE // -> undefined, obvisously 
    i = new Reminder(o); 
    i.TESTE() // -> outputs 'asd' 
}); 

Yani, nasıl angularjs anlamak almak objects'daki her nesne gerçek sonuçtur, bu nedenle örneklerin bir listesi gibi davranır? ...

Öneriler

geçici çözüm örneklerini oluşturarak sonuçlarına yineleme yeni bir liste oluşturmak için, ama değil en uygun değil mi? @rtcherry tarafından

Çözüm:

function RemindersCtrl ($scope, $rootScope, Reminder) { 
    $scope.reminders = Reminder.getList(); 
} 

: hatırlatmaları yükleniyor

.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; 
    }); 
}]) 

: rtcherry önerdiği gibi

, ben istek verilerinin okunması yapılandırılması restangular

kullanılan Özel yöntemimi Reminder'a ekle (n) Olarak ngResource gibi temiz, ama yapılabilir ot: ​​@moderndegree tarafından

.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; 
}]) 

Çözüm:

saf ngResource kullandı:

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; 
}]) 

Benim denetleyicisi:

Transaction.query(filter).$then(function (result) { 
    $scope.days = []; 
    var transactions = result.resource; 
    resource[0].remainingDays(); // it works 

}); 
+1

[Restangular] (https://github.com/mgonto/restangular) gibi bir şey denemek isteyebilirsiniz. – rtcherry

+0

whoa, iyi görünüyor .. Bakacağız –

+0

. Açısal bir kaynağa bir yöntem eklemek kadar kolay değil, ancak yapılabilir .. ama bir çok kullanışlı özellik üzerinde yeniden ödeme yapar. Yorumunuzdan bir cevap almak ister misiniz? –

cevap

6

aşağıdakileri yapmanız gerekir:

$resource('/api/v1/reminder/', {}, { 
    query: { 
     method: 'GET', 
     isArray: true, 
     transformResponse: $http.defaults.transformResponse.concat([ 
      function (data, headersGetter) { 
       return data.objects; 
      } 
     ]) 
    } 
}); 

Bu senin $HttpProvider 'ın varsayılan trafosuna dönüşümü ekler.

Not: Eğer bu konuda yanılıyorsam beni düzeltin ama bu özelliğin v1.1.2 veya daha büyük bir sürüm gerektirdiğini düşünüyorum.

+1

+1, AngularJS'nin 1.1.x şubesinden yeni 'ngResource' özelliklerini kullanan bir çözüm yayınlamak için. – rtcherry

+0

Denerim! Bir posta isteğiyle ilgili yanıt vermemeye özen gösteren bir sorunla karşılaşıyorum ve ngresource üzerinde çalıştı. daha sonra geri dönmek bana biraz zaman kazandıracak. –

+1

Serin. Yüklemeniz gereken kütüphanelerin sayısını sınırlamak her zaman iyidir. Ayrıca, son zamanlarda gönderdiğim ve benzer bir sorunu çözdüğüm bir cevap. http://stackoverflow.com/questions/17332922/how-can-i-insert-commands-before-or-prevent-https-jsonp-automatic-parsing-in-a/17333030#17333030 @Shaman bir yol arıyordu Yanıtı, varsayılan dönüştürmeden önce dönüştürmek için. –

4

Sen may restangular gibi bir şey denemek istiyorum.

Bu işi yapmak için gereken bazı yapılandırmalar vardır. Bir örnek here. Eğer ek bir kütüphane kullanmaktan kaçınmak istiyorsa

+0

Soruyu daha sonra çözüm koduyla güncelleyeceğim. –

3

meta nesnesini doğrudan Reminder.query() tarafından döndürülen sonuçlarda (Moderndegree'nin yanıtını genişleterek) korumak için aşağıdakileri yaptım.

var reminders = Reminder.query(...); 
console.log(reminders.meta); // Returns `meta` as expected. 

Ben response nesne mevcut olduğundan aynı zamanda Reminder.query callback'inde içindeki benzer bir şey yapmak mümkün olacağını düşünüyorum: Eğer döndürülen nesne üzerinde doğrudan meta değerini ulaşmasını sağlar

var Reminder = $resource('/api/v1/reminder/', {}, { 
    query: { 
    method: 'GET', 
    isArray: true, 
    transformResponse: $http.defaults.transformResponse.concat([ 
     function (data, headersGetter) { 
      return data.objects; 
     } 
    ]), 
    interceptor: { 
     response: function(response) { 
     response.resource.meta = response.data.meta; 
     } 
    } 
    } 
}); 

orada da var.

İlgili konular