What is the lifecycle of an AngularJS Controller?

Can someone please clarify what the lifecycle of an AngularJS controller is?

  • Is a controller a singleton, or created / destroyed on demand?
  • If the latter, what triggers the creation / destruction of the controller?

Consider the below example:

var demoApp = angular.module('demo')
  .config(function($routeProvider, $locationProvider) {
      .when('/home', {templateUrl: '/home.html', controller: 'HomeCtrl'})
      .when('/users',{templateUrl: '/users.html', controller: 'UsersCtrl'})
      .when('/users/:userId', {templateUrl: '/userEditor.html', controller: 'UserEditorCtrl'});

demoApp.controller('UserEditorCtrl', function($scope, $routeParams, UserResource) {
  $scope.user = UserResource.get({id: $routeParams.userId});


In the above example, when I navigate to /users/1,user 1 is loaded, and set to the $scope.

Then, when I navigate to /users/2, user 2 is loaded. Is the same instance of UserEditorCtrl reused, or is a new instance created?

  • If it’s a new instance, what triggers the destruction of the first instance?
  • If it’s reused, how does this work? (ie., the method to load the data appears to run on creation of the controller)


Well, actually the question is what is the life cycle for a ngView controller.

Controllers are not singletons. Anyone can create a new controller and they are never auto-destroyed. The fact is that it’s generally bound to the life cycle of its underlying scope. The controller is not automatically destroyed whenever its scope is destroyed. However, after destroying an underlying scope, its controller is useless (at least, by design, it should be).

Answering your specific question, a ngView directive (as well for ngController directive) will always create a new controller and a new scope every time a navigation happens. And the last scope is going to be destroyed as well.

The life cycle “events” are quite simple. Your “creation event” is the construction of your controller itself. Just run your code. To know when it gets useless (“destruction event”), listen to scope $destroy event:

$scope.$on('$destroy', function iVeBeenDismissed() {
  // say goodbye to your controller here
  // release resources, cancel request...

For ngView specifically, you are able to know when the content gets loaded through the scope event $viewContentLoaded:

$scope.$on('$viewContentLoaded', function readyToTrick() {
  // say hello to your new content here

Here is a Plunker with a concept proof (open your console window).