Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access Angular service when manually bootstrapping / initializing

Is it possible to access to a method of a factory service, before Angular has been bootstrapped, similar to the code below?

I need to make a number of AJAX requests before Angular starts in order to set a number of global application variables. I had hoped to keep the logic for this and/or store the responses inside an Angular service, and return a promise...

<script src="scripts/app.js"></script>
<script src="scripts/factories/app.js"></script>

<script>
    angular.element(document).ready(function() {

        factoryName.startup().then(function() {
            angular.bootstrap(document, ['MyApp']);
        }, function(err) {
            console.log(error fetching bootstrap data);
        }

    });
</script>

Is there an alternative method to use to get a similar behaviour?

like image 375
james Avatar asked Nov 11 '13 14:11

james


2 Answers

You can make the first service calls in module run blocks. When a later service call is made for those variables, you can either serve them out of $http's cache or have explicitly cached the promise from the first call.

// example
myApp.run(function(MyService) {
  // call your function when Angular starts up
  MyService.init();
});
like image 98
Emerson Farrugia Avatar answered Sep 18 '22 00:09

Emerson Farrugia


Below is an example that loads a configuration file before bootstrapping the application.

The first call to bootstrap is done to gain access to angular services like $http and $location (you could also inject your own module at this point to access custom services).

After the configuration file has been loaded, angular.bootstrap is called for the main application, with the loaded configuration set as a constant on a makeshift module(rsacAppBootstrap) that is injected.

Here are at least two advantages over using a promise set from a run block:

  1. Reduced boilerplate of promise for everything dependent on configuration
  2. Ability to conditionally load dependencies based on the environment using RequireJS

Custom bootstrap script:

angular.bootstrap().invoke(function ($http, $location) {

  var env = $location.search()._env || null;
  if (env === true) {
    env = null;
  }

  var configUri = 'config/env.json';
  if (env) {
    configUri = configUri.replace('json', env + '.json');
  }

  var rsacAppBootstrap = angular.module('rsacAppBootstrap', [])
    .run(function ($rootScope, $location, $window) {
      var env = $location.search()._env;
      $rootScope.$on('$locationChangeSuccess', function () {
        var newEnv = $location.search()._env;
        if (env !== newEnv) {
          $window.location.reload();
        }
      })
    });

  function bootstrap(config) {
    rsacAppBootstrap.constant('rsacConfig', config || {});
    angular.element(document).ready(function () {
      var modules = ['rsacApp', 'rsacAppBootstrap'];
      if (config.modules){
        config.modules.forEach(function(v){
          modules.push(v);
        })
      }
      angular.bootstrap(document, modules);
    });
  }

  $http.get(configUri)
    .success(function (config) {
      config._env = env;
      if (config.require) {
        require(config.require, function(){
          bootstrap(config);
        });
      } else {
        bootstrap(config);
      }
    })
    .error(function () {
      bootstrap();
    });

});

Example configuration file:

{
  "_meta": [
    "Development environment settings"
  ],

  "require":[
    "//code.angularjs.org/1.2.3/angular-mocks.js",
    "components/rsacMock/js/rsacMock.js"
  ],

  "modules":[
    "ngMockE2E",
    "rsacMock"
  ],

  "resources": { ... }

}
like image 20
Michael Allan Jackson Avatar answered Sep 21 '22 00:09

Michael Allan Jackson