android - 无法在 Controller 中操作工厂信息

标签 android angularjs sqlite cordova ionic-framework

我正在开发一个 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 :

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

有人能帮忙吗?

最佳答案

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

我正在考虑使用数据库的基础工作(我没有测试),通过全局变量将数据传递给 Controller ​​的整体方法是错误的,请不惜一切代价避免这种情况/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 :

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

希望 View 不会发生任何变化:

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

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

干杯,

关于android - 无法在 Controller 中操作工厂信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43380446/

相关文章:

sqlite - 最后 10 行的平均结果

android - 动画通知栏图标是否可以接受?

android - 如何从文件加载文本到textview

java - WebView缓存后台预加载

sqlite - 使用 SQLite ODBC 驱动程序使用什么连接字符串从 powerpivot 读取 sqlite 数据库

Android 数据库损坏,但可以在 SQLite 管理器中打开。可恢复?

android - Html.fromhtml 的 Textview 占用了不需要的空间

javascript - 使用 ng-show 和 $window.onload 在页面加载后显示元素

javascript - 有没有办法重新映射使用 ng-repeat 迭代的对象的键值?

javascript - Angular-modal-service 不显示模态