Modules allow you to create small, reusable segments of code that are isolated from the rest of your code.

This can be very useful when attempting to separate concerns to create extensible, reusable AngularJS code inside of your app.

Defining a Module

You can define a new module by specifying a second parameter to the .module() function.

The first parameter is the name of the module to append to or create.

The second parameter is a list of modules to inject into the newly created module.

Defining a Module
angular
.module('nameOfModule', [ 'ngRoute', 'ngResource', 'ngCookies', 'ngAnimate', /* You can inject a comma separated list of other modules here! */ ]);

So now we've got an empty module with some stuff injected into it.. that's not too much fun...

So let's figure out how to add stuff to it!

Appending to an Existing Module

After defining the desired module, as above, you should now be able to append controllers, filters, directives, and providers to it using the single-argument version of the function:

Appending to a Module
angular
.module('nameOfModule')
.constant('NameOfConstant', 0)
.value('NameOfValue', '')
.service('NameOfService', function($scope) {  })
.factory('NameOfFactory', function($scope) {  })
.provider('NameOfProvider', function($scope) {  })
.filter('NameOfFilter', function($scope) {  })
.directive('NameOfDirective', function($scope) {  })
.controller('NameOfController', function($scope, $location, $cookies) {
  // Add things to $scope to display them in a view template
});

Keep reading for more information about FiltersDirectivesProvidersControllers, Scopes, and Partial Views.

Advanced Techniques

There are some fancy techniques that you may want to utilize when defining a new module, such as specifying your desired paths, or defining defaults for HTTP requests.

These special blocks will only run once: when your app is first loaded into Angular.

The "config" Block

Sometimes services like $route or $http give the user a Provider that allows them to set defaults and configuration options in the .config() block of your module.

Example: Setting Up Basic Routes

Some examples of this are setting up default HTTP headers, or setting up the routes for your app.
NOTE: Values, Services, and Factories cannot be injected into the "config" block. Only Providers can be used in this context.

The "config" Block
angular
.module('nameOfModule', [])
.provider('NameOfProvider', function($scope) {  })
.config([ '$routeProvider', function($routeProvider) {
  $routeProvider.when('/login', {
    controller: 'LoginController', // Name of controller to use for this route
    templateUrl: '/app/login.html' // Path to the Partial View Template to use for this route
  })
  .when('/anotherPath', {
    controller: 'AnotherController',
    templateUrl: '/app/another/view.html 
  })
  /*
    We can chain as many of these together as we want to define a skeleton for our single-page application
  */
  .otherwise('/login'); // Where to route when the user navigates to an unrecognized path
}]);

The "run" Block

It is sometimes useful to have a piece of startup code that only runs once. An example of this is to watch the $rootScope for a particular event to be emitted.

In such a case, the "run" block is an appropriate place to call that code. 

Example: Routing users to the login page when they need to login

Below is an example that will watch the $rootScope for any route changes and check the user's login credentials.

If the user is not logged in, they are bounced out to the login page to provide them.

The "run" Block
angular
.module('nameOfModule', [])
.config([ '$routeProvider', function($routeProvider) {
  // Configuration as described above
}])
.run([ '$rootScope', '$location', 'AuthInfo', function($rootScope, $location, authInfo){
  $rootScope.$on( "$routeChangeStart", function(event, next, current) {
    if (authInfo.isAuth() === false) {
      // user needs to log in, redirect to /login
      if (next.templateUrl !== "/app/ndslabs/login.html") {
        $location.path("/login");
      }
    }
  });
}]);

Useful Patterns

Explicit Dependency Injection

Consider the block of code shown above:

Implicitly Injected Dependencies
angular
.module('nameOfModule')
.controller('NameOfController', function($scope, $location, $cookies) {
  // Add things to $scope to display them in a view template
});

What would this code reduce to if minified?

Minified With Implicitly Injected Dependencies
angular.module('nameOfModule').controller('NameOfController', function(a,b,c) {  });

Now the browser / angular have no idea that "a" used to be "$scope", but you might notice that the string constants are preserved.

This leads us to the following pattern of explicitly specifying the names / order of the injected dependencies in an array.

Explicitly Injected Dependencies
angular
.module('nameOfModule')
.controller('NameOfController',  [ '$scope', '$location', '$cookies', function($scope, $location, $cookies) {
  // Add things to $scope to display them in a view template
}]);

Using this pattern, any variable name can be safely substituted and our code can be minified without losing information necessary to execute it:

Minified With Explicitly Injected Dependencies
angular.module('nameOfModule').controller('NameOfController', [ '$scope', '$location', '$cookies', function(a,b,c) {  }]);
  • No labels