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.
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:
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 Filters, Directives, Providers, Controllers, 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.
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.
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:
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?
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.
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:
angular.module('nameOfModule').controller('NameOfController', [ '$scope', '$location', '$cookies', function(a,b,c) { }]);