前段时间,我在AngularJS中设置了一个抽象数据工厂,需要提示如何简化其使用。我最初的印象是,我将为每个实体创建另一个工厂,该工厂将从AngularJS控制器调用。事实证明它看起来太复杂了,我想删除中间实体工厂(ContentTypesFactory
),只需直接从AngularJS控制器调用抽象工厂。
在下面的例子中,我正在连接一个KendoUI数据源。
AbstractRepository.js:
app.factory('abstractRepository', [function () {
// we will inject the $http service as repository service
// however we can later refactor this to use another service
function abstractRepository(repositoryService, whichEntity, odataUrlBase) {
//this.http = $http;
this.http = repositoryService;
this.whichEntity = whichEntity;
this.odataUrlBase = odataUrlBase;
this.route;
}
abstractRepository.prototype = {
getList: function () {
return this.http.get(this.odataUrlBase);
},
get: function (id) {
return this.http.get(this.odataUrlBase + '/' + id);
},
insert: function (entity) {
return this.http.post(this.odataUrlBase, entity);
},
update: function (entity) {
return this.http.put(this.odataUrlBase + '/' + entity.ID, this.whichEntity);
},
remove: function (id) {
return this.http.delete(this.odataUrlBase + '/' + id);
}
};
abstractRepository.extend = function (repository) {
repository.prototype = Object.create(abstractRepository.prototype);
repository.prototype.constructor = repository;
}
return abstractRepository;
}]);
ContentTypesFactory.js:
/// <reference path="../Scripts/angular.min.js" />
/// <reference path="../app.js" />
/// <reference path="AbstractRepository.js" />
// each function returns a promise that can be wired up to callback functions by the caller
// the object returned from the factory is a singleton and can be reused by different controllers
app.factory('contentTypesRepository', ['$http', 'abstractRepository', function ($http, abstractRepository) {
var odataUrlBase = '/odata/ContentTypes'
var whichEntity = 'ContentTypes';
function contentTypesRepository() {
abstractRepository.call(this, $http, whichEntity, odataUrlBase);
}
abstractRepository.extend(contentTypesRepository);
return new contentTypesRepository();
}]);
ContentTypesController.js:
app.controller('contentTypesController', ['$scope', '$log', 'contentTypesRepository',
function ($scope, $log, contentTypesFactory) {
$scope.odataUrlBase = '/odata/ContentTypes';
$scope.status;
//
// Grid
//
$scope.contentTypesDataSource = new kendo.data.HierarchicalDataSource({
type: "odata",
transport: {
create: {
url: $scope.odataUrlBase
},
read: {
type: "GET",
url: $scope.odataUrlBase,
//function (data) {
// pass in the URL to the abstract factory
//},
dataType: "json" // the default result type is JSONP, but WebAPI does not support JSONP
},
update: {
contentType: "application/json",
url: function (data) {
return $scope.odataUrlBase + '(' + data.ContentTypesId + ')';
} . . .
现在,删除对ContentTypesFactory的引用,我的新控制器代码如下所示:
app.controller('contentTypesController', ['http', '$scope', '$log', 'abstractDataFactory',
// the abstract data factory accepts controller type parameters for RESTful CRUD
function ($scope, $log, abstractDataFactory) {
//function ContentTypeController($scope) {
var crudServiceBaseUrl = "/odata/ContentTypes";
var odataUrlBase = '/odata/ContentTypes'
var whichEntity = 'ContentTypes';
// Pulled the following code from the ControlerTypesFactory, but not sure how to implement it in this ContentTypesController:
//function contentTypesRepository() {
// abstractRepository.call(this, $http, whichEntity, odataUrlBase);
//}
//abstractRepository.extend(contentTypesRepository);
//return new contentTypesRepository();
$scope.greeting = 'Hola!';
var dataSource = new kendo.data.DataSource({
type: "odata",
transport: {
read: {
url: crudServiceBaseUrl,
dataType: "json"
},
update: { // PUT
url: function (data) {
console.log(data);
dataType: "json"
return crudServiceBaseUrl + "(" + data.ContentTypeId + ")";
},
error: function (e) {
console.log("error: " + e);
}
}, . . .
我确信改变并不那么困难,但我对Angular相当新。我如何连接它以便使用抽象存储库,并寻找任何其他Angular最佳实践和命名建议?
答案 0 :(得分:4)
今天早上重新审视一下,我相信我有一个有效的解决方案。
再次,我想删除中间工厂抽象,并且只有一个抽象数据获取工厂,我可以直接从每个控制器传递参数。
$http
被注入工厂,该工厂接收两个参数whichEntity
,odataUrlBase
,并在实例化时设置。工厂公开了像getList(odataOptions)
这样的方法。这些选项需要作为查询字符串的一部分与请求一起传递,并通过$http
的{{1}}完成。
将新的抽象工厂注入控制器,然后使用所需的参数进行实例化:
params
这是新的抽象工厂:
app.controller('contentTypeController', ['$scope', '$log', 'abstractFactory3',
function ($scope, $log, abstractFactory3) {
var dataFactory = new abstractFactory3("ContentType", "/odata/ContentType");
由于这是通过app.factory('abstractFactory3', function ($http) {
function abstractFactory3(whichEntity, odataUrlBase) {
this.whichEntity = whichEntity;
this.odataUrlBase = odataUrlBase;
}
abstractFactory3.prototype = {
getList: function (odataOptions) {
//var result = $http({
// url: this.odataUrlBase,
// method: 'GET',
// params: odataParams
//});
return $http.get(this.odataUrlBase, {
params: odataOptions
});
}
};
return abstractFactory3;
});
使用的,我们必须提取OData参数:
kendo.data.DataSource
成功var odataParams = kendo.data.transports["odata"].parameterMap(options.data, "read");
后,我们会将结果传回数据源的get
:
options
我意识到在我原来的问题中,控制器实际上是使用了Kendo传输,而不是我设置的Angular工厂。
所以我现在拥有的是:
角度控制器(KendoUI数据源) - &gt;角度数据工厂
我还重写了这个问题,以便更准确地反映整个问题的内容,并希望这对某人有所帮助。
还有一些其他的细微差别,比如获取和传递数据ID,对象,JSON.stringification,这些都是完整解决方案中最好的显示。希望以下有用:
AngularJS抽象数据工厂:
var dataSource = new kendo.data.DataSource({
type: "odata",
transport: {
read:
function (options) {
var odataParams = kendo.data.transports["odata"].parameterMap(options.data, "read");
dataFactory.getList(odataParams)
.success(function (result) {
options.success(result);
});
//$http({ // // example of using $http directly ($http injection was removed from this controller, as this is now handled by the abstract data factory)
// url: crudServiceBaseUrl,
// method: 'GET',
// params: odataParams
//})
//.success(function (result) {
// options.success(result);
//});
}, // update, create, destroy, . . .
AngularJS控制器:
app.factory('abstractFactory3', function ($http) {
function abstractFactory3(odataUrlBase) {
this.odataUrlBase = odataUrlBase;
}
abstractFactory3.prototype = {
getList: function (odataOptions) {
//var result = $http({
// url: this.odataUrlBase,
// method: 'GET',
// params: odataParams
//});
return $http.get(this.odataUrlBase, {
params: odataOptions
});
},
get: function (id, odataOptions) {
return $http.get(this.odataUrlBase + '/' + id, {
params: odataOptions
});
},
insert: function (data) {
return $http.post(this.odataUrlBase, data);
},
update: function (id, data) {
return $http.put(this.odataUrlBase + '(' + id + ')', data);
},
remove: function (id) {
return $http.delete(this.odataUrlBase + '(' + id + ')');
}
};
return abstractFactory3;
});
答案 1 :(得分:0)
您提到了最佳实践,我认为最好将数据源和操作留在工厂或服务中,例如您拥有的数据工厂。以下是一些具体的参考资料: