55

Is there a way I can execute some JavaScript code at start-up of my AngularJS application? I have some common code that I need to make sure runs before any of the app directives/controllers. I do not want to be tied to routes and ng-view, I need this to be a generic solution for any ng-app.

I thought I could use Module Config, and I actually tried that, but I am trying to call a service, which seems impossible to access on Module Load.

Jeroen
  • 53,290
  • 30
  • 172
  • 279
Michel Habib
  • 645
  • 1
  • 7
  • 14

3 Answers3

81

You can do like this,

var app = angular.module('myApp',[]);

app.run(function($rootScope) {
    //.....
});
mark-cs
  • 4,579
  • 21
  • 31
devo
  • 21,875
  • 18
  • 78
  • 125
  • 5
    This gives me race conditions for calls into controllers. It seems that not all controllers are ready when the function executes. – Dan Dec 02 '15 at 22:34
  • @Dan ...yes, ha. i meant routes. i'm experiencing the same thing -- unexpected behavior where the resolve fns of controllers are executing before the app.run block. – lyyons Dec 04 '15 at 19:45
  • 1
    I need to wait for an async $http call to complete (it fetches api key for tracking) – chovy Jun 15 '16 at 19:40
27

Short version

You need to use the module.run(initializationFn) function, where the actual method can depend on services. You can inject dependencies as per usual:

var app = angular
    .module('demoApp', [])
    .run(['$rootScope', function($rootScope) {
        $rootScope.bodyClass = 'loading';
        // Etc. Initialize here.
    }]);

The example has initialization dependent on $rootScope, but you can also inject services, etc.

Longer version

The relevant module.run documentation is rather terse, as are the other (excellent) answers. Let me combine it into a more verbose example, that also shows how to inject a factory created service in your initializationFn:

var app = angular.module('demoApp', []);

// Service that we'll also use in the .run method
app.factory('myService', [function() {
  var service = { currentItem: { started: new Date() } };
  
  service.restart = function() {
    service.currentItem.started = new Date();
  };
  
  return service;
}]);

// For demo purposes
app.controller('demoCtrl', ['$scope', 'myService', function($scope, myService) {
  $scope.header = 'Demo!';
  $scope.item = myService.currentItem;
  $scope.restart = myService.restart;
}]);

// This is where your initialization code goes, which
// may depend on services declared on the module.
app.run(['$window', 'myService', function($window, myService) {
  myService.restart();
  $window.alert('Started!');
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="demoApp" ng-controller='demoCtrl' ng-cloak>
  <h1>{{ header }}</h1>
  <p>Current item started: {{ item.started }}</p>
  <p><button ng-click="restart()">Restart</button></p>
</div>
Jeroen
  • 53,290
  • 30
  • 172
  • 279
  • is the longer version better and why ? – Xsmael Oct 17 '16 at 14:34
  • in the longer version can i use `this` instead of `service.` ? and then not return anything ? would that work the same way ? – Xsmael Oct 17 '16 at 14:37
  • The longer version is just the longer version *of the explanation*. The mechanics of both versions are exactly the same. – Jeroen Oct 22 '16 at 17:30
  • If you're confused about the use of `this` in either scenario I suggest reading up in [e.g. this other question](http://stackoverflow.com/q/3127429/419956) and related work, and come back to SO with a specific problem/question if you're left with a problem (comments to another question are not really a good place to ask new questions). – Jeroen Oct 22 '16 at 17:31
3

You can use the "run" function from the Module API: http://docs.angularjs.org/api/angular.Module

This code will be executed after injector creation so you should be able to get at the service you are looking to use.

Erstad.Stephen
  • 1,035
  • 7
  • 9