如何发送KendoUI数据源的OData参数,以抽象的RESTful AngularJS数据工厂? [英] How to send KendoUI data source OData parameters to an abstract RESTful AngularJS data factory?
问题描述
前段时间,我安装一个抽象的数据工厂AngularJS,并需要就如何简化它的使用提示。我最初的IM pression,我会为每个实体,将来自AngularJS控制器被称为创造另一个下属工厂。原来它只是看起来太复杂,我想去掉中间的实体工厂( ContentTypesFactory
),并简单地直接从AngularJS控制器调用抽象工厂。
Some time ago, I setup an abstract data factory in AngularJS, and need a hint on how to simplify its use. I was initially under the impression that I would create another factory per entity that would be called from an AngularJS controller. Turns out it just looks too complicated and I would like to remove the intermediary entity factory (ContentTypesFactory
), and simply call the abstract factory directly from the AngularJS controller.
在下面的例子中,我连线了KendoUI数据源。
In the following example I'm wiring up a KendoUI datasource.
AbstractRepository.js:
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:
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:
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,我的新控制器code是这样的:
Now, removing the reference to ContentTypesFactory, my new controller code looks like this:
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);
}
}, . . .
我敢肯定,改变并不难,但我是相当新的角度。我怎么能这样组装起来,以便使用抽象的存储库,并寻找其它任何角度的最佳实践和命名建议?
I'm sure the change is not that difficult, but I'm fairly new to Angular. How can I wire this up so to use the abstract repository, and looking for any other Angular best-practices and naming suggestions?
推荐答案
目前今早重新审视,我相信我有一个可行的解决方案。
Taking a fresh look at this this morning, I believe I have a working solution.
再一次,我想要删除中介工厂抽象,并只有一个抽象数据获取工厂,我可以在参数传递直接从每个控制器。
Once again, I wanted to remove the intermediary factory abstraction, and have only one abstract data fetching factory that I could pass in parameters directly from from each controller.
$ HTTP
注射进厂这需要两个参数 whichEntity
, odataUrlBase
,并在实例化设置。工厂公开的方法,如的GetList(odataOptions)
。这是一个需要与请求的查询字符串的一部分传承下去这些选项,并通过 $ HTTP
是这样做的 PARAMS
。
$http
is injected into the factory which takes in two parameters whichEntity
, odataUrlBase
, and are set upon instantiation. The factory exposes methods like getList(odataOptions)
. It is these options that are required to to be passed along with the requests as part of the query string, and are done so through $http
's params
.
新抽象工厂注入控制器,随后用所需的参数实例
The new abstract factory is injected into the controller, then instantiated with the required parameters:
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;
});
由于这是通过使用通过 kendo.data.DataSource
,我们要提取的OData参数:
Since this is being used through through a kendo.data.DataSource
, we have to extract the OData parameters:
var odataParams = kendo.data.transports["odata"].parameterMap(options.data, "read");
在成功 GET
,我们传回数据源的选项
的结果是:
Upon a successful get
, we pass back the data source's options
with the result:
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, . . .
我意识到,在我原来的问题,控制器在使用剑道运输,而不是角的工厂,我不得不设置的事实。
I realize that in my original question, the controller was in fact using the Kendo transport, rather than the Angular factory that I had setup.
那么,我现在拥有的是:
So what I have now is:
角控制器(KendoUI数据源) - >角度数据工厂
angular controller (KendoUI datasource) -> angular data factory
我还改写了问题,以便更准确地反映整个问题是什么,并希望这是对别人的帮助。
I have also reworded the question in order to more-accurately reflect what the entire problem was, and hope this is of assistance to someone.
有一些其他的细微差别,如获取和传递数据的ID,对象JSON.stringification是最好的完整的解决方案中。希望以下帮助:
There are some other little nuances, like getting and passing data ID's, objects, JSON.stringification that are best shown in a full solution. Hopefully the following helps:
AngularJS抽象数据工厂:
AngularJS abstract data factory:
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;
});
AngularJS控制器:
AngularJS Controller:
app.controller('contentTypeController', ['$scope', '$log', 'abstractFactory3',
// the abstract data factory accepts controller type parameters for RESTful CRUD
function ($scope, $log, abstractFactory3) {
var dataFactory = new abstractFactory3("/odata/ContentType");
var crudServiceBaseUrl = "/odata/ContentType";
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);
})
.error (function (error) {
console.log("data error");
});
},
update:
function (options) {
var data = options.data;
dataFactory.update(data.ContentTypeId, data)
.success(function (result) {
options.success(result);
})
.error(function (error) {
console.log("data error");
});
},
create:
function (options) {
var data = options.data;
data.ContentTypeId = "0"; // required for valid field data
dataFactory.insert(data)
.success(function (result) {
options.success(result);
})
.error(function (error) {
console.log("data error");
});
},
destroy:
function (options) {
var data = options.data;
dataFactory.remove(data.ContentTypeId)
.success(function (result) {
options.success(result);
})
.error(function (error) {
console.log("data error");
});
},
parameterMap: function (options, type) {
// this is optional - if we need to remove any parameters (due to partial OData support in WebAPI
if (operation !== "read" && options.models) {
return JSON.stringify({ models: options });
}
},
},
batch: false,
pageSize: 10,
serverPaging: true,
change: function (e) {
console.log("change: " + e.action);
// do something with e
},
schema: {
data: function (data) {
//console.log(data)
return data.value;
},
total: function (data) {
console.log("count: " + data["odata.count"]);
return data["odata.count"];
},
model: {
id: "ContentTypeId",
fields: {
ContentTypeId: { editable: false, nullable: true },
//UserId: {editable: false, nullable: false },
Description: { type: "string", validation: { required: true } },
//msrepl_tran_version: { type: "string", validation: { required: true } }
}
}
},
error: function (e) {
//var response = JSON.parse(e.responseText);
var response = e.status;
console.log(response);
}
});
$("#grid").kendoGrid({
dataSource: dataSource,
pageable: true,
height: 400,
toolbar: ["create"],
columns: [
{ field: "ContentTypeId", editable: false, width: 90, title: "ID" },
{ field: "Description", title: "Content Type" },
{ command: ["edit", "destroy"] }
],
editable: "inline"
});
}]);
这篇关于如何发送KendoUI数据源的OData参数,以抽象的RESTful AngularJS数据工厂?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!