Manually loading AngularJS from Cordova deviceready event
I am using Cordova 3.3.1-0.4.2 and Angular 1.2.13
I need to manually bootstrap Angular as soon as I receive the "deviceready" event in Cordova.
I am testing a Nexus 5s cordova run android
, but I have exactly the same behavior on an iPhone.
To keep things simple, JS works in the global document scope. The scripts are loaded before the tag is closed </body>
.
It works:
angular.bootstrap(document.getElementById("app"), ["MyApp"]);
This does not work:
function init(){
angular.bootstrap(document.getElementById("app"), ["MyApp"]);
}
document.addEventListener('deviceready', function () {
init();
}, true);
However, if I add alert("init")
to the init method that shows it is running. Also alert (angular) and alert (document.getElementById ("application")) show they exist.
I don't understand why, given that init () is called, it doesn't work when called from within the EventListener callback, but it does work when called directly.
Seems strange / unintuitive.
Anyone?
source to share
The best solution I have found is to load bootstrap Angular as usual and then load Cordova as a module that returns a promise that is resolved when the device is ready.
angular.module('fsCordova', [])
.service('CordovaService', ['$document', '$timeout', '$window', '$q',
function($document, $timeout, $window, $q) {
var defer = $q.defer();
this.ready = defer.promise;
// Backup in the case that we did not received the event
// This seemed to be necessary with some versions of Cordova
// when testing via 'cordova serve' in a web browser
// but when on-device the event is received correctly
var timoutPromise = $timeout(function() {
if ($window.cordova){
defer.resolve($window.cordova);
} else {
defer.reject("Cordova failed to load");
}
}, 1200);
angular.element($document)[0].addEventListener('deviceready', function() {
$timeout.cancel(timoutPromise);
defer.resolve($window.cordova);
});
}
]);
Using:
angular.module('app', ['fsCordova']).
run(['$window', function($window){
// init Fastclick
FastClick.attach(angular.element($window.document.body)[0]);
}]).
controller('AppCtrl', ['$scope', 'CordovaService',
function($scope, CordovaService){
$scope.ready = false;
// when cordova is ready
CordovaService.ready.then(
function resolved(resp) {
$scope.ready = true;
},
function rejected(resp){
throw new Error(resp);
}
);
}
]);
I have shared this bootstrap project here on GitHub
source to share
For those who actually want to manually activate angularjs after the cordic deviceready event, this should be used. you can also read the details about it here AngularJS + Cordova (updated and even better!)
'use strict';
var CordovaInit = function() {
var onDeviceReady = function() {
receivedEvent('deviceready');
};
var receivedEvent = function(event) {
console.log('Start event received, bootstrapping application setup.');
angular.bootstrap($('body'), ['c3aApp']); // Manually add and boot Angularjs
};
this.bindEvents = function() {
document.addEventListener('deviceready', onDeviceReady, false);
};
//If cordova is present, wait for it to initialize, otherwise just try to
//bootstrap the application.
if (window.cordova !== undefined) {
console.log('Cordova found, wating for device.');
this.bindEvents();
} else {
console.log('Cordova not found, booting application');
receivedEvent('manual')
}
};
$(function() {
console.log('Bootstrapping!');
new CordovaInit();
});
I personally chose this method because I needed to get some data from the SQlite db on the device for Angularjs config before Angularjs loads, and loading Angularjs first seems to break my code.
I have been using this method sometime now and everything works well.
// PLEASE CHECK THE ORDER OF YOUR .js FILES.
source to share
- According to the Cordova deviceready docs, you should attach to the deviceready event on the onLoad event
- You may be facing a javascript library ordering issue
I posted a blueprint for a solution I came up with that does not require delayed initialization via promises and has been tested reliably on multiple emulators and physical iOS and Android devices on my blog .
source to share