title: Cordova SQLite: Cannot read property 'transaction' of null
body: <p>I am trying to integrate SQLite into my Ionic app, but I keep getting <code>Cannot read property 'transaction' of null</code> while remote debugging or testing via the browser, when trying to query the DB for data on the device.</p>
  
  <p>So I have split up all of my configs, controllers and factories into separate files, all grouped by feature / module, so I inject each module's config file into the main app, and then inside of the config file I inject the controller and factory.</p>
  
  <p>I am not sure if the way that I've structured the app might be breaking something?</p>
  
  <p>Below I've listed all of the relevant files involved,</p>
  
  <p><strong><em>app.js</em></strong></p>
  
  <pre><code>var app = angular.module('app', ['ionic', 'ngCordova', 'app.config', 'login.config']);
  
  app.run(['$rootScope', '$ionicPlatform', 'DB', function($rootScope, $ionicPlatform, DB) {
  
      $ionicPlatform.ready(function() {
  
          if (window.cordova &amp;&amp; window.cordova.plugins.Keyboard) {
              cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
          }
  
          if (window.StatusBar) {
              StatusBar.styleDefault();
          }
  
          if(navigator.splashscreen) {
              navigator.splashscreen.hide();
          }
  
          DB.init();
  
      });
  
  }]);
  </code></pre>
  
  <p><strong><em>app.config.js</em></strong></p>
  
  <pre><code>var app = angular.module('app.config', ['app.controller', 'app.factory']);
  
  app.config(function($stateProvider, $urlRouterProvider, $httpProvider) {
  
      $stateProvider
          .state('app', {
              url: "/app",
              abstract: true,
              templateUrl: "templates/menu.html",
              controller: 'appController'
          });
  
      $urlRouterProvider.otherwise('/login');
  
  });
  
  app.constant('DB_CONFIG', {
      name: 'database.db',
      tables: [
          {
              name: 'users',
              columns: [
                  {name: 'id', type: 'integer primary key'},
                  {name: 'username', type: 'text'},
                  {name: 'password', type: 'text'},
                  {name: 'api_key', type: 'text'},
                  {name: 'active', type: 'integer'}
              ]
          }
      ]
  });
  </code></pre>
  
  <p><strong><em>app.factory.js</em></strong></p>
  
  <pre><code>var appFactory = angular.module('app.factory', []);
  
  appFactory.factory('DB', ['$q', '$cordovaSQLite', 'DB_CONFIG', function($q, $cordovaSQLite, DB_CONFIG) {
  
      var db = null;
  
      var init = function() {
  
          db = $cordovaSQLite.openDB({ name: DB_CONFIG.name });
          // I use this when testing in browser db = window.openDatabase(DB_CONFIG.name, '1.0', 'database', -1);
  
          _.each(DB_CONFIG.tables, function(table) {
  
              var columns = [];
  
              _.each(table.columns, function(column) {
  
                  columns.push(column.name + ' ' + column.type);
  
              });
  
              var sql = 'CREATE TABLE IF NOT EXISTS ' + table.name + ' (' + columns.join(',') + ')';
  
              console.log('Table ' + table.name + ' initialized');
  
              query(sql);
  
          });
  
      };
  
      var query = function(sql, bindings) {
  
          bindings = typeof bindings !== 'undefined' ? bindings : [];
  
          return $cordovaSQLite.execute(db, sql, bindings);
  
      };
  
      var fetchAll = function(result) {
  
          var output = [];
  
          for (var i = 0; i &lt; result.rows.length; i++) {
              output.push(result.rows.item(i));
          }
  
          return output;
      };
  
      var fetch = function(result) {
          return result.rows.item(0);
      };
  
      return {
          init: init,
          query: query,
          fetchAll: fetchAll,
          fetch: fetch
      };
  }]);
  </code></pre>
  
  <p><strong><em>login.config.js</em></strong></p>
  
  <pre><code>var loginConfig = angular.module('login.config', ['ionic', 'login.controller']);
  
  loginConfig.config(function($stateProvider) {
  
      $stateProvider
  
          .state('login', {
              url: "/login",
              templateUrl: "modules/login/views/login.html",
              controller: 'loginController'
          });
  
  });
  </code></pre>
  
  <p><strong><em>login.controller.js</em></strong></p>
  
  <pre><code>var loginController = angular.module('login.controller', []);
  
  loginController.controller('loginController', ['$scope', '$state', 'DB', function($scope, $state, DB) {
  
      $scope.doLogin = function() {
  
          var username = this.username;
          var password = this.password;
  
          DB.query('SELECT * FROM users WHERE username = ? and password = ?', [username, password]).then(function(result){
              console.log(result);
          }, function(error){
              console.log(error);
          });
  
      };
  
  }]);
  </code></pre>
  
  <p>The user has already been inserted into the database, and sometimes it works, and I get the results back, most times it doesn't, and I get the above mentioned error.</p>
  
  <p>I am assuming this is because the DB is not initialising in time, before I query the database?</p>
  
  <p>If so, is there a way that I can make 100% sure that the database has loaded before I query it?</p>