最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Manually bootstrapping AngularJS from Cordova deviceready event - Stack Overflow

programmeradmin1浏览0评论

I'm using Cordova 3.3.1-0.4.2 and Angular 1.2.13

I need to manually bootstrap Angular once I get the Cordova 'deviceready' event.

I'm testing on a Nexus 5 with cordova run android but am having exactly the same behaviour on an iPhone.

To simplify the problem this is JS running in the global document scope. Scripts are being loaded before the closing </body> tag.


This works:

angular.bootstrap(document.getElementById("app"), ["MyApp"]);

This doesn't 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("app")) show that they exist.

I don't understand why, given that init() is being called, it doesn't work when called from the EventListener callback yet it does work if called directly.

Seems weird / unintuitive.

Anyone?

I'm using Cordova 3.3.1-0.4.2 and Angular 1.2.13

I need to manually bootstrap Angular once I get the Cordova 'deviceready' event.

I'm testing on a Nexus 5 with cordova run android but am having exactly the same behaviour on an iPhone.

To simplify the problem this is JS running in the global document scope. Scripts are being loaded before the closing </body> tag.


This works:

angular.bootstrap(document.getElementById("app"), ["MyApp"]);

This doesn't 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("app")) show that they exist.

I don't understand why, given that init() is being called, it doesn't work when called from the EventListener callback yet it does work if called directly.

Seems weird / unintuitive.

Anyone?

Share Improve this question asked Feb 18, 2014 at 0:52 AdeAde 3,0414 gold badges33 silver badges49 bronze badges 9
  • deviceready event is used for using the cordova API – Jonathan de M. Commented Feb 18, 2014 at 1:03
  • Yes, it's deviceready from the Cordova API that the EventListener is listening for. – Ade Commented Feb 18, 2014 at 1:05
  • So why bootstraping angularJS when cordova is ready? Angular do not need cordova API to be ready to run, you could call the deviceready after bootstraping angular. – Jonathan de M. Commented Feb 18, 2014 at 1:06
  • I don't know why, but bumping it down the event loop with a setTimeout(init,0) might work.. – calebboyd Commented Feb 18, 2014 at 3:13
  • 1 you should listen for device ready in your outermost angularjs controller, after bootstraping ng – Jonathan de M. Commented Feb 18, 2014 at 16:24
 |  Show 4 more ments

3 Answers 3

Reset to default 5

The best solution I've found is to bootstrap Angular as normal and then load Cordova as a module that returns a promise, which 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);
    });  
  }
]);

Usage:

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've shared this bootstrap project here on GitHub

To those who actually want to manually boostrap angularjs after cordova deviceready event should use this. you can also read details of 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 SQlite db on the device for Angularjs configuration before Angularjs loads, and loading Angularjs first seems to break my code.

I have been using this method for sometime now and everything works well.

// PLEASE DO CHECK THE ORDER OF YOUR .js FILES.

  1. According to the Cordova deviceready docs, you are supposed to attach to the deviceready event in the onLoad event
  2. You maybe hitting a javascript library ordering problem

I posted the outline of a solution I came up with that does not require deferred initialization via promises and has been tested to work reliability on multiple emulators and physical iOS and Android devices on my blog.

发布评论

评论列表(0)

  1. 暂无评论