如何将 KendoUI 数据源 OData 参数发送到抽象的 RESTful AngularJS 数据工厂? [英] How to send KendoUI data source OData parameters to an abstract RESTful AngularJS data factory?

查看:12
本文介绍了如何将 KendoUI 数据源 OData 参数发送到抽象的 RESTful AngularJS 数据工厂?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

前段时间,我在 AngularJS 中设置了一个抽象数据工厂,需要一个关于如何简化它的使用的提示.我最初的印象是我将为每个实体创建另一个工厂,该工厂将从 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 的引用,我的新控制器代码如下所示:

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

我确信改变并不那么困难,但我对 Angular 还是很陌生.我如何将其连接起来以使用抽象存储库,并寻找任何其他 Angular 最佳实践和命名建议?

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 被注入工厂,它接受两个参数whichEntityodataUrlBase,并在实例化时设置.工厂公开诸如 getList(odataOptions) 之类的方法.正是这些选项需要作为查询字符串的一部分与请求一起传递,并且通过 $httpparams 完成.

$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后,我们将数据源的options与结果传回:

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

我意识到在我最初的问题中,控制器实际上使用的是 Kendo 传输,而不是我设置的 Angular 工厂.

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.

所以我现在拥有的是:

角度控制器(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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆