【问题标题】:Unable to manipulate information of factory in controller无法在控制器中操作工厂信息
【发布时间】:2017-09-08 21:04:42
【问题描述】:

我正在开发一个 Angular 应用程序。我需要在 SQLite 中创建一个数据库,以便在我的 Android 项目中本地使用。我看到的每个教程都教我在工厂中制作并在其他页面中调用它。

问题是,在很多情况下,我需要获取这些信息并对其进行操作。我已经能够在表单中显示它,但不幸的是,我无法操作从工厂返回的对象。

我的代码如下。

工厂 sqlite:

var db = null;
var clienteselec = [];
var sqlite = angular.module('sqlite', ['ionic', 'ngCordova']);

sqlite.run(function ($ionicPlatform, $cordovaSQLite, $window) {
    $ionicPlatform.ready(function () {
        db = $cordovaSQLite.openDB({ name: "rollers.db", location: 1 });

        $cordovaSQLite.execute(db, "CREATE TABLE IF NOT EXISTS clientes (id integer primary key, nome varchar(40))");
        $cordovaSQLite.execute(db, "CREATE TABLE IF NOT EXISTS instalacao (id integer primary key, idCliente int, dataInst datetime)");
        $cordovaSQLite.execute(db, "CREATE TABLE IF NOT EXISTS manutencao (id integer primary key, idCliente int, idInstalacao int, dataManut datetime)");
        $cordovaSQLite.execute(db, "CREATE TABLE IF NOT EXISTS equipamento (id integer primary key, idInstalacao int, idManutencao int, TC int autoincrement, posicao varcar(1), Rolo varchar(40), dataEquip datetime)");
    });
})

sqlite.factory('clientesFactory', function ($cordovaSQLite, $rootScope) {
    return {
insert: function (Nome) {
            var query = "INSERT INTO clientes (nome) VALUES (?);";
            var values = [Nome];

            $cordovaSQLite.execute(db, query, values).then(
              function (res) {
                  alert('Cliente Cadastro com Sucesso!');

                  $cordovaSQLite.execute(db, "SELECT max(id) as id from clientes", []).then(
                      function (res) {
                          if (res.rows.length > 0) {
                              var valores = res.rows.item(0);
                              $rootScope.idCliente = valores.id;
                          }
                      }
                  );
              },
              function (err) {
                  alert('Cliente não cadastrado. Estamos verificando o problema!');
              }
            );
        },

        selectTodos: function(tab){
            var query = "SELECT * FROM " + tab;

            clienteselec = [];
            $cordovaSQLite.execute(db, query,[]).then(function (result) {
                if(result.rows.length){
                    for (var i = 0; i < result.rows.length; i++) {
                        clienteselec.push(result.rows.item(i));
                    }
                }else{
                    console.log("no data found!");
                }
            }, function(err){
                console.log("error" + err);
            });
        },
});

控制器:

.controller('ClienteCtrl', ['clientesFactory', '$scope', '$state', '$window', '$rootScope', function (clientesFactory, $scope, $state, $window, $rootScope) {
    $scope.listaClientes = function() {
        clientesFactory.insert('teste');
        clientesFactory.selectTodos('clientes');
        $scope.seleciona = clienteselec;
    }
}])

HTML:

<ion-content padding>

    <div ng-controller="ClienteCtrl">
        <button ng-click="listaClientes()">Novo Cliente</button>
        <!--<table>
            <tr ng-repeat="cli in clientes">
                <td></td>
            </tr>
        </table>-->    
        <ion-item ng-repeat="cli in seleciona">
            {{cli.nome}}
            <button ng-click="cadastraCliente({{cli.id}})">Novo</button>
            <button ng-click="instala({{cli.id}}, {{cli.nome}})">Instalação</button>
            <button ng-click="excluiCliente({{cli.id}}, {{cli.nome}})">Excluir</button>
    </div>

</ion-content>

谁能帮忙?

【问题讨论】:

    标签: android angularjs sqlite cordova ionic-framework


    【解决方案1】:

    您的代码存在很多架构问题,但在您开始新事物时这很正常。 :)

    我正在考虑使用数据库的基础工作(我没有测试),通过全局变量将数据传递给控制器​​的整体方法是错误的,请在角度上不惜一切代价避免这种情况/javascript 世界。

    您需要考虑更多,比如模块化或面向对象,并尝试封装它。如果不这样做,您的代码将非常脆弱并且容易出错,因为即使是脚本的顺序也可能会破坏它。

    我对你的代码做了一些调整,见下文:

    工厂:

    angular.module('sqlite', ['ionic', 'ngCordova'])
    .run(function ($ionicPlatform, $cordovaSQLite) {
        $ionicPlatform.ready(function () {
            var db = $cordovaSQLite.openDB({ name: 'rollers.db', location: 1 });
    
            $cordovaSQLite.execute(db, 'CREATE TABLE IF NOT EXISTS clientes (id integer primary key, nome varchar(40))');
            $cordovaSQLite.execute(db, 'CREATE TABLE IF NOT EXISTS instalacao (id integer primary key, idCliente int, dataInst datetime)');
            $cordovaSQLite.execute(db, 'CREATE TABLE IF NOT EXISTS manutencao (id integer primary key, idCliente int, idInstalacao int, dataManut datetime)');
            $cordovaSQLite.execute(db, 'CREATE TABLE IF NOT EXISTS equipamento (id integer primary key, idInstalacao int, idManutencao int, TC int autoincrement, posicao varcar(1), Rolo varchar(40), dataEquip datetime)');
        });
    })
    //I will not recommend you to use rootScope like that.
    //I added $q to work with the  $cordovaSQLite promises
    .factory('clientesFactory', function ($cordovaSQLite, $q /*$rootScope*/) {
    
        //local variables, no needs to be global
        var db = $cordovaSQLite.openDB({ name: 'rollers.db', location: 1 });
    
        //better approach for legibility
        return {
            insert: insert,
            selectTodos: selectTodos
        };
    
        function insert(Nome) {
            var query = 'INSERT INTO clientes (nome) VALUES (?);';
            var values = [Nome];
    
            //since this is a assynchronous method            
            //we can return this promise and let the caller lead with it
            return $cordovaSQLite.execute(db, query, values)
                .then(function () {
    
                    var deferred = $q.defer();
                    // returns the data in the promise sucess
                    deferred.resolve('Cliente Cadastro com Sucesso!');
    
                    /*
                    //This is really necessary?
                    //If so, why not to convert it in another method?
                    $cordovaSQLite.execute(db, 'SELECT max(id) as id from clientes', []).then(
                        function (res) {
                            if (res.rows.length > 0) {
                                var valores = res.rows.item(0);
                                $rootScope.idCliente = valores.id;
                            }
                        }
                    );*/
                })
                .catch(function () { //promises have a catch method to capture the error
                    //returns the data with error 
                    deferred.reject('Cliente não cadastrado. Estamos verificando o problema!');
    
                });
        }
    
        function selectTodos(tab) {
            var query = 'SELECT * FROM ' + tab;
    
            //since this is a assynchronous method            
            //we can return this promise and let the caller lead with it
            return $cordovaSQLite.execute(db, query, [])
                .then(function (result) {
                    var deferred = $q.defer();
    
                    if (!result.rows.length) {
                        //returns the data with error 
                        deferred.reject('No data found!');
                    }
    
                    var clienteselec = [];
                    for (var i = 0; i < result.rows.length; i++) {
                        clienteselec.push(result.rows.item(i));
                    }
    
                    //returns the data in the promise sucess
                    deferred.resolve(clienteselec);
                })
                .catch(function (err) {  //promises have a catch method to capture the error
                    console.log('error' + err);
                });
        }
    })
    

    控制器:

    .controller('ClienteCtrl', ['clientesFactory', '$scope', '$state', '$window', '$rootScope', function (clientesFactory, $scope, $state, $window, $rootScope) {
    
        $scope.listaClientes = listaClientes;
        $scope.seleciona = [];
    
    
        function listaClientes() {
            //Now, let the promise magic happens 
            //and lead with it here in the controller logic
            clientesFactory.insert('teste')
                .then(function (response) {
                    console.log(response);
                })
                .catch(function (err) {
                    //use console.error to show erros :)
                    console.error(err);
                });
    
            clientesFactory.selectTodos('clientes')
                .then(function (response) {
                    $scope.clienteselec = response;
                })
                .catch(function (err) {
                    //use console.error to show erros :)
                    console.error(err);
                });
        }
    }]);
    

    希望视图不会改变:

    <ion-content padding>
    
    <div ng-controller="ClienteCtrl">
        <button ng-click="listaClientes()">Novo Cliente</button>
        <ion-item ng-repeat="cli in seleciona">
            {{ cli.nome }}
            <button ng-click="cadastraCliente({{cli.id}})">Novo</button>
            <button ng-click="instala({{cli.id}}, {{cli.nome}})">Instalação</button>
            <button ng-click="excluiCliente({{cli.id}}, {{cli.nome}})">Excluir</button>
    </div>
    

    免责声明:我不会在任何地方运行此代码,因此我很确定这不会按原样运行。您将需要进行必要的调整,希望这将为您提供如何将数据从服务(工厂)传递到控制器的整体方法,以及一些良好的编程实践。如果您想了解更多关于如何以正确的方式制作 Angular 应用程序,我强烈建议您查看 John Papa 的 Angular 样式指南:https://github.com/johnpapa/angular-styleguide

    干杯,

    【讨论】:

    • 非常感谢您对 gvsrepins 的帮助。我会像你那样测试承诺,如果有效,我会做出回应。
    • 我很乐意帮助@FelipeF。 :) 如果此答案符合您的需求,请将其标记为您问题的答案。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-14
    • 1970-01-01
    • 1970-01-01
    • 2014-03-30
    • 1970-01-01
    • 2012-04-02
    相关资源
    最近更新 更多