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?

+1


source to share


3 answers


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

+4


source


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.

+1


source


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

0


source







All Articles