In a previous project, where I was not using Angular, I setup a Kendo.DataSource
that used an OData endpoint as follows:
var userDS = new kendo.data.DataSource({
type: "odata",
transport: {
read: {
url: "/api/Users?$filter=USERGROUPS/any(usergroup: usergroup/ID eq '" + groupData.ID + "')", // only need to expand users for the selected group
dataType: "json", // the default result type is JSONP, but WebAPI does not support JSONP
},
update: {
url: function (data) {
// TODO: write UpdateEntity controller method
return "/api/Users(" + groupData.ID + ")";
},
dataType: "json"
},
destroy: {
url: function (data) {
// TODO: write Delete controller method
return "/api/Users(" + groupData.ID + ")";
},
dataType: "json"
},
parameterMap: function (options, type) {
// this is optional - if we need to remove any parameters (due to partial OData support in WebAPI
var parameterMap = kendo.data.transports.odata.parameterMap(options);
return parameterMap;
}
},
Now, introducing AngularJS into the mix, I would like to know how to define the read
, update
and destroy
events using my AngularJS factory, where there is no URL.
My factory contracts are setup as follows:
contentTypesFactory.getList()
contentTypesFactory.insert(contentType)
contentTypesFacotry.remove(id)
The first problem I see with .getList()
is that it doesn't take in any query string parameters, like $orderby
and $inlinecount=allpages
which I need for use with the KendoUI Grid. It is inside this factory that the URL is defined, then calls an abstract factory (see below).
I need to somehow pass in the URL and the entity name to my factory from the kendo.datasource
url: function (remember, that the grid control will append whatever OData querystring parameters are required).
So, how I would setup the factory to output the data expected for each of the CRUD events.
Data source definition:
$scope.contentTypesDataSource = new kendo.data.HierarchicalDataSource({
type: "odata",
transport: {
read: {
//url: "/api/UserGroups?$orderby=GROUPNAME",
url: '/odata/ContentTypes',
//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: {
},
destroy: {
},
parameterMap: function (options, type) { ...
Abstract repository:
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:
// 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();
}]);
After looking at kendo-examples-asp-net, I'm thinking that I should do away with the ContentTypesFactory
and the abstract repository and call the OData endpoint directly - of course this is relatively easy.
However, my initial reason for creating an Angular repository was so that I could do JS unit testing on the data functions. To retain this feature, how can I call the abstract repository directly from the data source functions, and this the recommended way of accomplishing this?