Ala*_* H. 15 angularjs angularjs-factory angularjs-resource
我有一个模型,定义使用$resource,我成功加载.
正如所承诺的,每个加载的实例都是我定义的类的实例.
(以下示例来自Angular文档.在其中,User.get结果是一个对象instanceof User.)
var User = $resource('/user/:userId', {userId:'@id'});
Run Code Online (Sandbox Code Playgroud)
但是,想象每个用户来自这样的电线:
{
"username": "Bob",
"preferences": [
{
"id": 1,
"title": "foo",
"value": false
}
]
}
Run Code Online (Sandbox Code Playgroud)
我定义了一个Preference为Preference对象添加有价值方法的工厂.但是当用户加载时,这些preferences不是Preference自然的.
我试过这个:
User.prototype.constructor = function(obj) {
_.extend(this, obj);
this.items = _.map(this.preferences, function(pref) {
return new Preference(pref);
});
console.log('Our constructor ran'); // never logs anything
}
Run Code Online (Sandbox Code Playgroud)
但它没有任何效果,也从未记录任何东西.
如何使我的Users' preferences数组中的每个项目成为一个实例Preference?
And*_*lin 12
$ resource是一个简单的实现,缺少这样的东西.
User.prototype.constructor什么都不做; 与其他库不同,angular不会尝试像面向对象那样行事.这只是javascript.
..但幸运的是,你有承诺和javascript :-).这是你可以做到的一种方式:
function wrapPreferences(user) {
user.preferences = _.map(user.preferences, function(p) {
return new Preference(p);
});
return user;
}
var get = User.get;
User.get = function() {
return get.apply(User, arguments).$then(wrapPreferences);
};
var $get = User.prototype.$get;
User.prototype.$get = function() {
return $get.apply(this, arguments).$then(wrapPreferences);
};
Run Code Online (Sandbox Code Playgroud)
您可以将其抽象为一个装饰任何资源方法的方法:它接受一个对象,一个方法名称数组和一个装饰器函数.
function decorateResource(Resource, methodNames, decorator) {
_.forEach(methodNames, function(methodName) {
var method = Resource[methodName];
Resource[methodName] = function() {
return method.apply(Resource, arguments).$then(decorator);
};
var $method = Resource.prototype[methodName];
Resource.prototype[methodName] = function() {
return $method.apply(this, arguments).$then(decorator);
};
});
}
decorateResource(User, ['get', 'query'], wrapPreferences);
Run Code Online (Sandbox Code Playgroud)
您可以通过覆盖内置资源操作来转换请求和响应来执行此操作(请参阅文档中的transformRequest和transformResponse.):
var m = angular.module('my-app.resources');
m.factory('User', [
'$resource',
function($resource) {
function transformUserFromServer(user) {
// Pass Preference directly to map since, in your example, it takes a JSON preference as an argument
user.preferences = _.map(user.preferences, Preference);
return user;
}
function transformUserForServer(user) {
// Make a copy so that you don't make your existing object invalid
// E.g., changes here may invalidate your model for its form,
// resulting in flashes of error messages while the request is
// running and before you transfer to a new page
var copy = angular.copy(user);
copy.preferences = _.map(user.preferences, function(pref) {
// This may be unnecessary in your case, if your Preference model is acceptable in JSON format for your server
return {
id: pref.id,
title: pref.title,
value: pref.value
};
});
return copy;
}
function transformUsersFromServer(users) {
return _.map(users, transformUserFromServer);
}
return $resource('/user/:userId', {
userId: '@id'
}, {
get: {
method: 'GET',
transformRequest: [
angular.fromJson,
transformUserFromServer
]
},
query: {
method: 'GET',
isArray: true,
transformRequest: [
angular.fromJson,
transformUsersFromServer
]
},
save: {
method: 'POST',
// This may be unnecessary in your case, if your Preference model is acceptable in JSON format for your server
transformRequest: [
transformUserForServer,
angular.toJson
],
// But you'll probably still want to transform the response
transformResponse: [
angular.fromJson,
transformUserFromServer
]
},
// update is not a built-in $resource method, but we use it so that our URLs are more RESTful
update: {
method: 'PUT',
// Same comments above apply in the update case.
transformRequest: [
transformUserForServer,
angular.toJson
],
transformResponse: [
angular.fromJson,
transformUserFromServer
]
}
}
);
};
]);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9275 次 |
| 最近记录: |