我必须建立一个angularjs客户端的API输出JSON是这样的:
{
"count": 10,
"next": null,
"previous": "http://site.tld/api/items/?start=4"
"results": [
{
"url": "http://site.tld/api/items/1.json",
"title": "test",
"description": "",
"user": "http://site.tld/api/users/4.json",
"creation_datetime": "2013-05-08T14:31:43.428"
},
{
"url": "http://site.tld/api/items/2.json",
"title": "test2",
"description": "",
"user": "http://site.tld/api/users/1.json",
"creation_datetime": "2013-05-08T14:31:43.428"
},
{
"url": "http://site.tld/api/items/3.json",
"title": "test3",
"description": "",
"user": "http://site.tld/api/users/2.json",
"creation_datetime": "2013-05-08T14:31:43.428"
}
]
}
我怎样才能让一个$resource
映射到这一点? 如果我使用isArray=false
,我会得到整个BLOB作为一个对象,可用于阅读,但我不能说.put()
就可以了。 如果我使用isArray
,这是行不通的。
有没有干净的方式做到这一点? 或者我应该回去使用$http
?
你有几个选项。 如果你可以改变服务器的输出,你可以添加元信息(计数,下一个,上)的标头值,而不是在响应主体加入其中。
你的第二个选择是改造与transformResponse响应。 这是可作为角一个$响应配置V1.1.2和以后 (不稳定分支):
var Data = $resource('./data.json',{},{
list:{isArray:true,method:'get',
transformResponse: function (data, headers) {
return JSON.parse(data).results;
}}
});
如果你不希望使用不稳定的分支,也可以改变$ HTTP,其中价值资源的使用:
$http.defaults.transformResponse.push(function(data){
if(data && data.results){
return data.results;
}
});
我已经创建了两个例子plunker: http://plnkr.co/edit/PmYotP0eo5k41Z6ZCxl4?p=preview
我不知道什么传递的元数据到应用程序的其它部分的最佳方法(如果需要的话)。 你可以将其追加到第一个结果,或将其添加为一个单独的对象 - 也许不那么优雅,但它会完成这项工作。
我知道这个问题是有点老了。 但我认为,答案不包括主要的问题 - 如何获取分页信息以及如何保持资源特色为对象的名单。
你有basicly两种解决方案,分页程序的数据传递到头变换中的信息或使用$ HTTP,然后手动实例化项目。
1.Transform消息
在这里,我重新定义查询,把拼版数据为标题。
集管不是数组 - 它是“headersGetter”,其通过调用标题(“页眉名称”)返回报头,并通过调用标头返回内对象()。 我要设置标题小写。
var PAGINATION_TOTAL = 'pagination-total-elements';
var PAGINATION_SIZE = 'pagination-size';
...
.factory('BeerResourceFactory', function($resource, API_URI) {
return $resource(API_URI + '/beer/:id',
{'id': '@id'},
{
'update': {method: 'PUT'},
'query' : {method: 'GET', isArray:true, transformResponse : function(data, headers) {
var jsonData = JSON.parse(data);
headers()[PAGINATION_TOTAL] = jsonData.totalElements;
headers()[PAGINATION_SIZE] = jsonData.size;
return jsonData.content;
}}
});
})
从那以后,我定义服务,这种封装和头采取分页。 Sudenly我们不能用$ promise.then()和retrurn结果,因为承诺得到只会导致作为参数,而不是headersGetter,所以我们必须使用普通的回调,并创建自己的诺言。
.service('beerService', function(BeerResourceFactory, $q) {
this.query = function(filter) {
var defer = $q.defer();
BeerResourceFactory.query(filter, function(result, headers) {
var promiseResult = {
beers: result,
paging: {
totalItems: headers(PAGINATION_TOTAL),
perPage: headers(PAGINATION_SIZE)
}
};
defer.resolve(promiseResult);
});
return defer.promise;
}
2,使用$ http和实例资源
当使用$ http来代替资源,还有就是你仍然想使用数组的元素作为资源实例,并能够调用$保存/ $删除的问题,所以它是可以手动实例化它们。 在这里,您也可以使用普通的承诺作为ussual。
.service('beerService', function($http, BeerResourceFactory, API_URI) {
this.query = function(filter) {
return $http.get(API_URI + '/beer', {params: filter})
.then(function(response) {
var transformedList = response.data.content.map(function(element) {
return new BeerResourceFactory(element);
});
return {
beers: transformedList,
paging: {
totalItems: response.data.totalElements,
perPage: response.data.size
}
};
});
};
我宁愿第二个解决方案,因为它更简单。
我难倒了这个问题为好,这里是为我工作。 添加响应变压器它会使用数组结果和手动创建的资源对象,我以为ngResource会在内部做无妨。
var Plan = $resource(apiPath + 'plans/:planId/', {planId:'@id'}, {
query: {
isArray: false,
transformResponse: function(response){
response = angular.fromJson(response);
response.results = response.results.map(function(plan) {
return new Plan(plan);
});
return response;
}
},
});
到现在为止,这是更老,但我设法在一个单一的资源工厂来解决这个问题:
.factory('BeerResourceFactory', function($resource, API_URI) {
var resource = $resource(API_URI + '/beer/:id',
{'id': '@id'},
{
'update': {method: 'PUT'},
'query' : {method: 'GET', isArray:true, transformResponse : function(data) {
var jsonData = angular.fromJson(data);
jsonData.beers = jsonData.beers.map(function (beer) {
return new resource(beer)
});
return jsonData.content;
}}
});
return resource;
})