我在AngularJS上写了几篇关于访问Tastypie API的资源.一切工作正常,除了一个细节:tastypie总是将实际结果封装在
JSON的对象属性中,例如:
/ API / V1 /提醒/:
{ 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",repeat: "weekly",resource_uri: "/api/v1/reminder/1",value: "-50" },{ category: { color: "#999999",due_date: "2010-10-17",id: 2,resource_uri: "/api/v1/reminder/2",value: "-50" } }
使用回调到get()调用是很痛苦的:
Reminder.get().$then(function (result) { $scope.reminders = result.data.objects; });
但是我知道result.resource是一个实际的Reminder实例.
.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; }])
现在我需要在我的提醒类上实现行为,我需要我的Meta.objects上的每一个元素都是一个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' });
那么,我如何得到angularjs来了解对象上的每个对象是实际的结果,所以它的行为就像一个实例列表?
解决办法是创建一个新的列表,迭代创建实例的结果,但它不是最佳的…
建议?
@rtcherry解决方案:
根据rtcherry的建议,我用了restangular
配置读取请求数据:
.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; }); }])
载入提醒:
function RemindersCtrl ($scope,$rootScope,Reminder) { $scope.reminders = Reminder.getList(); }
将我的自定义方法添加到提醒(不如ngResource那么干净但可行):
.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; }])
@moderndegree的解决方案
我使用纯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','$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; }])
我的控制器:
Transaction.query(filter).$then(function (result) { $scope.days = []; var transactions = result.resource; resource[0].remainingDays(); // it works });
如果您想避免使用其他库,您应该可以执行以下操作:
$resource('/api/v1/reminder/',{ query: { method: 'GET',transformResponse: $http.defaults.transformResponse.concat([ function (data,headersGetter) { return data.objects; } ]) } });
这将附加您的转换为$HttpProvider的默认变压器.
注意:如果我错了,我相信这个功能需要v1.1.2或更高版本.