2013-06-26 28 views
10

Tôi có ít tài nguyên được viết trên AngularJS truy cập API Tastypie. Tất cả mọi thứ hoạt động tốt, ngoại trừ một chi tiết: tastypie luôn đóng gói kết quả thực tế bên trong một thuộc tính objects trên JSON, ví dụ:AngularJS và JSON phức tạp được trả về bởi django tastypie

/api/v1/reminder/:

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

Đó là WASY để sửa chữa bằng cách sử dụng gọi lại cho get() cuộc gọi :

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

Nhưng tôi biết result.resource là phiên bản Reminder thực tế.

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

Bây giờ tôi cần phải thực hiện hành vi trên lớp Reminder của tôi, và tôi cần mọi phần tử trên meta.objects tôi là một thể hiện của Reminder:

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

Vì vậy, làm thế nào để tôi nhận được angularjs phải hiểu rằng mọi đối tượng trên objects là kết quả thực tế để nó hoạt động như một danh sách các trường hợp?

Giải pháp thay thế là tạo danh sách mới lặp lại trên kết quả tạo các trường hợp, nhưng không tối ưu ...

Gợi ý?

Solution bởi @rtcherry:

Theo đề nghị của rtcherry, tôi sử dụng restangular

Cấu hình đọc yêu cầu dữ liệu:

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

Loading the nhắc nhở:

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

Thêm phương thức tùy chỉnh của tôi vào Reminder (n ot càng sạch càng ngResource, nhưng doable):

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

Solution bởi @moderndegree:

tôi đã sử dụng tinh khiết ngResource:

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

điều khiển của tôi:

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

}); 
+1

Bạn có thể muốn thử một cái gì đó như [restangular] (https://github.com/mgonto/restangular). – rtcherry

+0

whoa, có vẻ tốt .. tôi sẽ xem xét nó –

+0

xong. nó không dễ dàng như việc thêm phương thức vào tài nguyên góc cạnh, nhưng có thể được thực hiện .. nhưng restangular trả tiền trên đó là nhiều tính năng hữu ích. bạn có muốn đưa ra câu trả lời từ nhận xét của mình để tôi có thể đánh dấu nó không? –

Trả lời

6

Nếu bạn muốn tránh sử dụng một thư viện bổ sung, bạn sẽ có thể làm như sau:

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

này sẽ nối chuyển đổi của bạn để biến mặc định $HttpProvider 's.

Lưu ý: Đúng nếu tôi sai trên trang này nhưng tôi cho rằng tính năng này yêu cầu v1.1.2 hoặc cao hơn.

+1

+1 để đăng giải pháp sử dụng các tính năng 'ngResource' mới hơn từ nhánh 1.1x của AngularJS. – rtcherry

+0

Tôi sẽ thử! Tôi đang gặp phải một số vấn đề với restangular không cho tôi phản hồi về yêu cầu đăng bài và nó hoạt động trên ngresource. hoàn nguyên về sau sẽ giúp tôi tiết kiệm thời gian. –

+1

Tuyệt. Nó luôn luôn là tốt để hạn chế số lượng thư viện bạn phải tải. Ngoài ra, đây là một câu trả lời tôi đăng gần đây đã giải quyết được một vấn đề tương tự. http://stackoverflow.com/questions/17332922/how-can-i-insert-commands-before-or-prevent-https-jsonp-automatic-parsing-in-a/17333030#17333030 @Shaman đang tìm kiếm một cách để chuyển đổi phản hồi trước biến đổi mặc định. –

4

Bạn có thể muốn thử một cái gì đó như restangular.

Có một số cấu hình cần thiết để thực hiện công việc đó. Ví dụ là here.

+0

Tôi sẽ cập nhật câu hỏi của mình sau bằng mã giải pháp. –

3

Tôi đã thực hiện như sau để bảo vệ đối tượng meta trực tiếp trên các kết quả được trả về bởi Reminder.query() (mở rộng câu trả lời từ @moderndegree).

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

đó cho phép bạn để có được những giá trị meta trực tiếp trên đối tượng trả về:

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

tôi nghĩ rằng nó cũng sẽ có thể làm điều gì đó tương tự bên trong gọi lại từ Reminder.query kể từ khi đối tượng response có sẵn ở đó.

Các vấn đề liên quan