Comment envoyer les paramètres OData de source de données KendoUI à une source de données abstraite RESTful AngularJS?

Il y a quelque temps, j'ai configuré une usine de données abstraite dans AngularJS et j'ai besoin d'un indice pour simplifier son utilisation. J'ai d'abord l'impression que je créerais une autre usine par entité qui serait appelée à partir d'un contrôleur AngularJS. Il s'avère qu'il semble trop compliqué et j'aimerais supprimer l'usine d'entités intermédiaires ( ContentTypesFactory ) et appeler simplement l'usine abstraite directement du contrôleur AngularJS.

Dans l'exemple suivant, je câblage une source de données 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 + ')'; } . . . 

Maintenant, en supprimant la référence à ContentTypesFactory, mon nouveau code de contrôleur ressemble à ceci:

 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); } }, . . . 

Je suis sûr que le changement n'est pas si difficile, mais je suis assez nouveau chez Angular. Comment puis-je câbler ceci afin d'utiliser le référentiel abstrait, et à la recherche de toutes les autres meilleures pratiques angulaires et des suggestions de dénomination?

Je regarde ce matin ce matin, je crois que j'ai une solution de travail.

Une fois de plus, je voulais supprimer l'abstraction de l'usine intermédiaire et avoir une seule source d'extraction de données abstraites que je pourrais transmettre directement les paramètres à partir de chaque contrôleur.

$http est injecté dans l'usine qui prend en deux paramètres whichEntity , odataUrlBase , et sont définis lors de l'instanciation. L'usine expose des méthodes comme getList(odataOptions) . Ce sont ces options qui doivent être transmises avec les requêtes dans le cadre de la chaîne de requête, et sont effectuées dans les params $http .

La nouvelle usine abstraite est injectée dans le contrôleur, puis elle est instanciée avec les paramètres requis:

 app.controller('contentTypeController', ['$scope', '$log', 'abstractFactory3', function ($scope, $log, abstractFactory3) { var dataFactory = new abstractFactory3("ContentType", "/odata/ContentType"); 

Voici la nouvelle usine abstraite:

 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; }); 

Puisque cela est utilisé à travers un kendo.data.DataSource , nous devons extraire les paramètres OData:

 var odataParams = kendo.data.transports["odata"].parameterMap(options.data, "read"); 

Lors d'une réussite, nous retrouvons les options de la source de données avec le résultat:

  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, . . . 

Je me rends compte que dans ma question initiale, le contrôleur utilisait en fait le transport Kendo, plutôt que l'usine Angular que j'avais installée.

Donc, ce que j'ai maintenant, c'est:

Contrôleur angulaire (source de données KendoUI) -> usine de données angulaires

J'ai également reformulé la question afin de mieux réfléchir sur l'intégralité du problème et j'espère que cela est utile pour quelqu'un.

Il y a d'autres petites nuances, comme obtenir et transmettre des ID de données, des objets, une synchronisation JSON.les meilleures représentations dans une solution complète. Espérons que ce qui suit contribue:

L'usine de données abstraites 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; }); 

Contrôleur AngularJS:

 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" }); }]); 

Vous parlez des meilleures pratiques, je pense qu'il vaut mieux laisser votre source de données et vos manipulations dans une usine ou un service comme les usines de données que vous aviez. Voici quelques références spécifiques: