In this article, I build on Part 1 of this series and introduce you to using modules and services to organize your application components. After viewing this article, you will have concise and important knowledge for starting your first Angular application using these advanced concepts.
Most applications have separate areas of concern for dividing up workflows. In some languages, these are called components, which are a strict set of business rules that handle a particular set of tasks. In other languages, these workflow rules are referred to as modules.
Scripting languages often refer to components as modules because a module is really just a lightweight component. The primary usage for modules is code reusability. With that said, let's learn about what modules mean to Angular.
Modules
If you look on the web for the definition of module in Angular, you will likely get mixed answers. I have seen the definition referenced to mean that a module is an application. Others say a module is a collection of dependencies. I think the best way to describe the Angular module concept is to think of them like components in other languages.
Components are simply a collection of classes and interfaces that implement a unit of functionality. For example, an engine has components, and this is also true in the software world.
One component handles a set of operations, and the sum of the components make up the engine as a whole. So if a module were like a component, it would make sense that a module could be reused across different applications. You could also assume that modules, like components, use a namespace or package name to identify them. With this in mind, let's take a look at an example in Angular that uses a module.
Let's say your application has a page for users to check some email. The email page, call it MyMailer.htm, can have its own controller and services that serve this view (MyMailer). It is quite common to have a controller, service, and model that serve a single view.
If we create a module that handles MyMailer, all of the MyMailer dependencies are wrapped together in this one module, which can be used across the rest of the application or other applications. To define a module, use the following syntax:
var myMailer = angular.module('MyMailer', []);
So what about the controller(s) and services(s) to be used by this module? Where do they come from? Now that we have a module, both controllers and services can be attached to the module.
For example, to declare a service for the module, use this syntax:
myMailer.service('messageService', function(){
this.messages = [{sender:foo@yahoo.com, subject:Hello,message:Hello from Foo.}, sender:bar@yahoo.com, subject:Hello,message:Hello from Bar.}];
});
It is important to note that this module declaration code would be made available to a controller that serves the view (in this case, the view called MyMailer.htm).
To display these messages in a list, we could have a List page that uses the controller that contains the scope binding for the MyMailer module having the messages provided by the messageService, thus binding this scope to our List view.
To demonstrate, see the following sample list.htm code:
<body ng-app="MyMailer">
<h1>Email Messages</h1>
<table ng-controller="ListController">
<tr ng-repeat="message in messages ">
<td>{{message.sender}}</td>
<td>{{message.subject}}</td>
<td>{{message.message}}</td>
</tr>
</table>
</body>
Now, check out what is in the controller (controllers.js) to make this work:
function ListController($scope, messageService) {
$scope.messages = messageService.messages;
}
As you can see, the controller is the binding between the view and the controller. For larger applications, you would have a model that sits between the controller and the view. The model would contain the implementation details in a service.
The ng-app directive refers to the module that can be used on just one view-usually a view template. The module holds the routing configuration or rules for reaching pages, which is discussed in the next section.
Routing
To make this simple example more complete, let's add a routing configuration to the MyMailer module. To add a routing configuration, place the following code into the application's controllers.js file:
function emailRouteConfig($routeProvider) {
$routeProvider.
when('/', {
controller: ListController,
templateUrl: 'list.htm'
}).
}
myMailer.config(emailRouteConfig);
In the code, there is more dependency injection using an Angular built-in service for routing ($route) that uses a method called 'when' to define url routing paths that map the path to a controller.
For example, when we go to the app and hit the MyMailer.htm page, the routing configuration forwards the request to the list.htm page that is using the ListController.
To make the routing available, we have to pass it to the module's config function, as shown above. More routes can be easily added by just repeating the 'when' code block.
The last part of this example is to add the MyMailer.htm page shown below that serves as the entry point to the application:
<html ng-app="MyMailer">
<head>
<title>My Mailer</title>
<script type="text/javascript"
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script>
<script src="src/controls.js"></script>
<body>
<div ng-view></div>
</body>
</html>
Notice that you need very little for this page because it already knows what to do by including the controls.js file, which handles the routing, service, module, and controller declarations for each view.
Conclusion
In this article you learned more-advanced concepts of the AngularJS framework, which is essential for exploring and fast-track learning of Angular.
Try building a simple web application that expands the example application in this article. For example, add a details.htm page to display email message details.
The next step is to learn how Angular works with web forms and databases, which, as you may have guessed, is mostly through Ajax-like functionality.