Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using $ionicPlatform.ready() in module.js before plugins are initialized #8

Open
pbernasconi opened this issue Jun 2, 2014 · 32 comments
Labels
Milestone

Comments

@pbernasconi
Copy link
Collaborator

@pbernasconi pbernasconi commented Jun 2, 2014

What do you think about returning a promise in the module which uses $ionicPlatform.ready() to make sure the plugins are not used until the dom is ready?

angular.module('ngCordova', [ngCordova.plugins])
  .factory('ngCordova', function ($q, $rootScope, $ionicPlatform) {
    var deferred = $q.defer();

    $ionicPlatform.ready(function () {
      console.log('ionic is ready');
      $rootScope.$apply(deferred.resolve);
    });

    return {
      ready: function () {
        return deferred.promise;
      }
    };
  })
  .run(function (ngCordova) {});

Then each plugin uses the ngCordova service service like so:

.factory('Notification', function ($q, ngCordova) {
  return {
    alert: function (message, alertCallback, title, buttonName) {              
       ngCordova.ready().then(function () {
          navigator.notification.alert(message, alertCallback, title, buttonName);
       });
    }
  };
});
@rtpm

This comment has been minimized.

Copy link

@rtpm rtpm commented Jun 4, 2014

This is a must imho, but I would use a "deviceready" event instead of $ionicPlatform.ready().

@krik

This comment has been minimized.

Copy link

@krik krik commented Jun 4, 2014

Yeah, "deviceready" would be cool!

@sidneys

This comment has been minimized.

Copy link
Contributor

@sidneys sidneys commented Jun 4, 2014

+1

@EnchanterIO

This comment has been minimized.

Copy link

@EnchanterIO EnchanterIO commented Jun 6, 2014

Ah I killed last two hours trying to figure out why this isn't working... then I tried to wrap it all with timeout for 5s and wuala...

Until your suggestion will be in the official cordova api what do you guys think is the cleanest way to solve my situation please ?

LandingPage
 .controller('landingPageCtrl', ['$scope','$cordovaDevice','$timeout',
     function($scope, $cordovaDevice, $timeout) {
         $scope.onlineOrNot = {
             text: 'not'
         };

        $timeout(function() {
            var device = $cordovaDevice.getDevice();
            var cordova = $cordovaDevice.getCordova();
            var model = $cordovaDevice.getModel();
            var platform = $cordovaDevice.getPlatform();
            var uuid = $cordovaDevice.getUUID();
            var version = $cordovaDevice.getVersion();

            $scope.onlineOrNot.text = version;

        },5000);

        $scope.onlineOrNot.text = "not breaking anymore";

    }
])
@quanghoc

This comment has been minimized.

Copy link

@quanghoc quanghoc commented Jun 9, 2014

I believe the ionic.js already had deviceready embeded in $ionicPlatform.ready so getting a separate deviceready would be redundant.

  function onWindowLoad() {
    if(ionic.Platform.isWebView()) {
      // the window and scripts are fully loaded, and a cordova/phonegap
      // object exists then let's listen for the deviceready
      document.addEventListener("deviceready", onPlatformReady, false);
    } else {
      // the window and scripts are fully loaded, but the window object doesn't have the
      // cordova/phonegap object, so its just a browser, not a webview wrapped w/ cordova
      onPlatformReady();
    }
    window.removeEventListener("load", onWindowLoad, false);
  }

The problem is services and controllers module would load before the $ionicPlatform.ready being called in app.js. So I would not suggest implementing ngCordova.ready() per plugin as @pbernasconi mentioned. That would have some overhead (although tiny). I would use ionic.Platform in http://ionicframework.com/docs/angularjs/utils/platform/ or $ionicPlatform like below:

controller('MyCtrl', function($scope, $ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Your code
    $scope.$digest();
  });
});

Make sure to put the $scope.$digest(); at the end if you want to update angular rendering engine.

I am wondering if there is a better way to detect ionicPlatform ready even before loading angular modules for Cordova only.

@mlynch

This comment has been minimized.

Copy link
Member

@mlynch mlynch commented Jun 9, 2014

We should add a separate, non ionic-prefixed thing here. It's okay if they overlap since they will both fire correctly.

Maybe something like $cordova which has some functions like

$cordova.ready(function() {
});
@quanghoc

This comment has been minimized.

Copy link

@quanghoc quanghoc commented Jun 9, 2014

Yeah something as an overall "umbrella" prior to loading angular modules would work. So that there is no ready() check here and there in the controllers. It's necessary to load everything upfront anyways.

@romgar

This comment has been minimized.

Copy link
Contributor

@romgar romgar commented Jul 11, 2014

An another way is to initialize angular dynamically when cordova is ready.

window.ionic.Platform.ready(function() {
    angular.bootstrap(document, ['<your_main_app']);
});

Works like a charm.

@okonon

This comment has been minimized.

Copy link

@okonon okonon commented Jul 11, 2014

Hey @Natsu- how does this behave when developing in a browser? Cordova ready is not fired while in a browser. Does it still bootstraps the app?

@romgar

This comment has been minimized.

Copy link
Contributor

@romgar romgar commented Jul 11, 2014

Yes, app is also bootstrapped in a browser.
Look at ionic.Platform.ready() description (from ionic code source) :

    /**
     * @ngdoc method
     * @name ionic.Platform#ready
     * @description
     * Trigger a callback once the device is ready, or immediately
     * if the device is already ready. This method can be run from
     * anywhere and does not need to be wrapped by any additonal methods.
     * When the app is within a WebView (Cordova), it'll fire
     * the callback once the device is ready. If the app is within
     * a web browser, it'll fire the callback after `window.load`.
     * @param {function} callback The function to call.
     */
@nicowenterodt

This comment has been minimized.

Copy link

@nicowenterodt nicowenterodt commented Aug 6, 2014

Hi @Natsu- , I tested your approach. Works good in browsers. But on iOS it fails - ending up with a white screen.

I removed the ng-app directive from the body tag and bootstrapped it like you said within the Platform.ready ..

@romgar

This comment has been minimized.

Copy link
Contributor

@romgar romgar commented Aug 6, 2014

Do you have some error logs ? On XCode / Safari web inspector ?

@nicowenterodt

This comment has been minimized.

Copy link

@nicowenterodt nicowenterodt commented Aug 6, 2014

There were no errors shown within the console. But now I wrapped that into a try- block and catched the exception with an alert so I found out that the error was the following:

undefined is not an object window.cordova.plugins.Keyboard
ionic.Platform.ready(function(){
  try{
    angular.bootstrap(document.body, ['my_app']);     
  }
  catch(e){
    alert(e)
  }
})

in app.js

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
})

As soon as I removd the Keyboard-Plugin lines it starts working.. so I double checked the installed plugins and found out that for any reason I don't now the keyboard plugin was not configured anymore in the ios.json

Afer reinstalling the Plugin it now works.

cordova plugin add https://github.com/driftyco/ionic-plugins-keyboard.git

Thanks @Natsu- for your approach. Works perfectly for me now.

@romgar

This comment has been minimized.

Copy link
Contributor

@romgar romgar commented Aug 7, 2014

Well done !

@pbernasconi pbernasconi modified the milestone: v0.2.0-beta Sep 3, 2014
@emertechie

This comment has been minimized.

Copy link

@emertechie emertechie commented Sep 14, 2014

I was able to use the resolve feature of the UI router to wait for ionic.Platform.ready signal before each state that might need a plugin:

$stateProvider
    .state('screen', {
        url: '/screen',
        abstract: true,
        templateUrl: 'templates/layout.html',
        resolve: {
            cordova: function($q) {
                var deferred = $q.defer();
                ionic.Platform.ready(function() {
                    console.log('ionic.Platform.ready');
                    deferred.resolve();
                });
                return deferred.promise;
            }
        }
    })
@quanghoc

This comment has been minimized.

Copy link

@quanghoc quanghoc commented Sep 14, 2014

Then you still have to check for the cordova variable inside the controller. It's not different from using ionic.Platform.ready directly.

@emertechie

This comment has been minimized.

Copy link

@emertechie emertechie commented Sep 15, 2014

@quanghoc Perhaps I'm missing something but the promise returned from the resolve.cordova fully resolves before my controller is called (even if I don't declare a cordova parameter) so I don't have to wait on anything in the controller. This way, I only need one call to ionic.Platform.ready in an abstract state and not repeated in multiple controllers.

@quanghoc

This comment has been minimized.

Copy link

@quanghoc quanghoc commented Sep 15, 2014

Oh I think you're right.

We must state to the users this solution require the use of ui-router

@simoneb

This comment has been minimized.

Copy link

@simoneb simoneb commented Oct 12, 2014

@natsu perfect approach!

@pbernasconi

This comment has been minimized.

Copy link
Collaborator Author

@pbernasconi pbernasconi commented Oct 19, 2014

A new WIP is happening @ #386. Would love to hear your thoughts and comments

krizroring added a commit to krizroring/ng-cordova that referenced this issue Dec 21, 2014
Changed the install link back to the original author, after acceptance of pul request ionic-team#8 on the master branch of phonegap-plugin-brightness.
@JerryBels

This comment has been minimized.

Copy link

@JerryBels JerryBels commented Jan 3, 2015

Any news about this ? Adding the "ready" condition to the plugins ?

@matiasurbano

This comment has been minimized.

Copy link
Contributor

@matiasurbano matiasurbano commented Feb 13, 2015

Same as @JerryBels, there is any news about it?

@ms88privat

This comment has been minimized.

Copy link

@ms88privat ms88privat commented Apr 25, 2015

+1 ?

@simpixelated

This comment has been minimized.

Copy link

@simpixelated simpixelated commented Jul 23, 2015

@pbernasconi blogged about adding this on the Ionic blog back in December 2014, but it's still hasn't been added. Would love to hear some news.

@alexkavon

This comment has been minimized.

Copy link

@alexkavon alexkavon commented Jul 23, 2015

+1 to what @simpixelated said

@mbarzeev

This comment has been minimized.

Copy link

@mbarzeev mbarzeev commented Jul 27, 2015

+1 for @emertechie abstract view suggestion

@Stajor

This comment has been minimized.

Copy link

@Stajor Stajor commented Sep 30, 2015

+1

@alexkavon

This comment has been minimized.

Copy link

@alexkavon alexkavon commented Sep 30, 2015

Here's a nice work around I found for this recently:
http://stealthcode.co/multiple-calls-to-ionicplatform-ready/

@sgentile

This comment has been minimized.

Copy link

@sgentile sgentile commented Oct 13, 2015

I've wasted hours here, why would all the examples show ,

ie.  if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {
                cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
                cordova.plugins.Keyboard.disableScroll(true);

            } 

If none of the plugins are loaded on $ionicPlatform.ready ? when my app starts I need to register notifications, I do this on run and use $ionicPlatform.ready - but I'm seeing the behavior where where window.cordova isn't defined

@bitflower

This comment has been minimized.

Copy link

@bitflower bitflower commented Nov 11, 2015

I used @romgar's solution posted here. #8 (comment)

@eduardo-marcolino

This comment has been minimized.

Copy link

@eduardo-marcolino eduardo-marcolino commented Jul 27, 2017

@emertechie thanks for the code!
It worked using $routeProvider too:

    $routeProvider
        .when('/', {
            templateUrl: 'views/home.html',
            controller: 'homeController',
            resolve: {
              cordova: function($q) {
                 var deferred = $q.defer();
                 document.addEventListener("deviceready", function () {
                   console.log('ionic.Platform.ready');
                   deferred.resolve();
                 });
                 return deferred.promise;
              }
            }
        })
@julitroalves

This comment has been minimized.

Copy link

@julitroalves julitroalves commented Aug 17, 2017

Thanks @romgar, it works for me too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.