我正在寻找Angular的CRUD通用工厂(我目前更喜欢使用服务):
app.factory('dataFactory', ['$http', function ($http) { var urlBase = '/odata/ContentTypes'; // The _object_ defined in the factory is returned to the caller, rather than as with a service, // where the _function_ defined in the service is returned to the caller var dataFactory = {}; dataFactory.getContentTypes = function () { var contentTypes = $http.get(urlBase); return contentTypes; }; dataFactory.getContentType = function (id) { return $http.get(urlBase + '/' + id); }; dataFactory.insertContentType = function (contentType) { return $http.post(urlBase, contentType); }; dataFactory.updateContentType = function (contentType) { return $http.put(urlBase + '/' + contentType.ID, contentType); } dataFactory.deleteContentType = function (id) { return $http.delete(urlBase + '/' + id); } // to traverse navigation properties //dataFactory.getUserFromContentTypeId = function (id) { // return $http.get(urlBase + '/' + id + '/user'); //} //dataFactory.getOrders = function (id) { // return $http.get(urlBase + '/' + id + '/orders'); //}; return dataFactory; }]);
对于我所有的实体,此代码将大致相同。是否可以注入实体名称(或相应的RESTful路径),如果可以,可以将其视为局部类,如果需要其他承诺(例如遍历导航属性),也可以注入它们?
如果可以使用Angular做到这一点,有人可以发布一些示例吗?
就我个人而言,我希望代码保持干燥状态,并且发现,如果在服务器API上保持通用约定,则可以使用基本工厂/存储库/类或任何您想调用的名称走很长一段路。我在AngularJs中实现此目标的方法是使用AngularJs工厂,该工厂返回基本存储库类,即工厂返回带有原型定义而不是对象实例的javascript类函数,我称之为abstractRepository。然后,针对每个资源,为该典型资源从原型继承的具体资源创建一个具体的存储库abstractRepository,因此我继承了所有共享/基本功能,abstractRepository并为具体存储库定义了任何资源特定的功能。
abstractRepository
我认为一个例子会更清楚。假设您的服务器API使用以下URL约定(我不是最纯REST的人,所以我们将把约定留给您要实现的任何约定):
GET -> /{resource}?listQueryString // Return resource list GET -> /{resource}/{id} // Return single resource GET -> /{resource}/{id}/{resource}view // Return display representation of resource PUT -> /{resource}/{id} // Update existing resource POST -> /{resource}/ // Create new resource etc.
我个人使用Restangular,因此以下示例基于该示例,但是您应该可以轻松地将其调整为$http或$resource。
$http
$resource
app.factory('abstractRepository', [function () { function abstractRepository(restangular, route) { this.restangular = restangular; this.route = route; } abstractRepository.prototype = { getList: function (params) { return this.restangular.all(this.route).getList(params); }, get: function (id) { return this.restangular.one(this.route, id).get(); }, getView: function (id) { return this.restangular.one(this.route, id).one(this.route + 'view').get(); }, update: function (updatedResource) { return updatedResource.put(); }, create: function (newResource) { return this.restangular.all(this.route).post(newResource); } // etc. }; abstractRepository.extend = function (repository) { repository.prototype = Object.create(abstractRepository.prototype); repository.prototype.constructor = repository; }; return abstractRepository; }]);
具体的存储库,让我们以客户为例:
app.factory('customerRepository', ['Restangular', 'abstractRepository', function (restangular, abstractRepository) { function customerRepository() { abstractRepository.call(this, restangular, 'customers'); } abstractRepository.extend(customerRepository); return new customerRepository(); }]);
然后在您的控制器中注入customerRepository:
customerRepository
app.controller('CustomerController', ['$scope', 'customerRepository', function($scope, customerRepository) { // Use your customerRepository }]);
如果使用这种基本存储库模式,您会发现大多数CRUD控制器也将共享许多通用代码,因此我通常会创建一个基本CRUD控制器,我的控制器使用继承该基本CRUD控制器$injector.invoke,但我将保留以下示例这超出了这个问题的范围。
$injector.invoke