如何将KendoUI数据源OData参数发送到抽象的RESTful AngularJS数据工厂?

时间:2014-02-10 14:22:07

标签: javascript jquery angularjs kendo-ui factories

前段时间,我在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最佳实践和命名建议?

2 个答案:

答案 0 :(得分:4)

今天早上重新审视一下,我相信我有一个有效的解决方案。

再次,我想删除中间工厂抽象,并且只有一个抽象数据获取工厂,我可以直接从每个控制器传递参数。

$http被注入工厂,该工厂接收两个参数whichEntityodataUrlBase,并在实例化时设置。工厂公开了像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)

您提到了最佳实践,我认为最好将数据源和操作留在工厂或服务中,例如您拥有的数据工厂。以下是一些具体的参考资料: