mercredi 11 février 2015

Cordova SQLite: Cannot read property 'transaction' of null

I am trying to integrate SQLite into my Ionic app, but I keep getting Cannot read property 'transaction' of null while remote debugging or testing via the browser, when trying to query the DB for data on the device.


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.


I am not sure if the way that I've structured the app might be breaking something?


Below I've listed all of the relevant files involved,


app.js



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 && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}

if (window.StatusBar) {
StatusBar.styleDefault();
}

if(navigator.splashscreen) {
navigator.splashscreen.hide();
}

DB.init();

});

}]);


app.config.js



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


app.factory.js



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


login.config.js



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'
});

});


login.controller.js



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

};

}]);


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.


I am assuming this is because the DB is not initialising in time, before I query the database?


If so, is there a way that I can make 100% sure that the database has loaded before I query it?


Aucun commentaire:

Enregistrer un commentaire