Table of contents

< Previous chapterNext chapter >

Last updated .

Structuring the app with modules

Any non-trivial application needs a way to structure its various parts. Otherwise, the code and markup quickly becomes a mess (aka spaghetti) which is difficult to understand, test and maintain. The .Net environment offers several constructs to compartmentalize and isolate stuff. First, an app can be divided into several assemblies. Within an assembly, namespaces are used to logically group related types. In javascript there are no fancy constructs like assemblies or namespaces, let alone classes. However, the Angular module was invented as a way to divide components of an application into manageable chunks. This honors the principle of separation of concerns and facilitates testing.

A module is the container of all the other Angular components, such as directives, services and controllers. In the previous chapters, we have already used modules a lot; there wouldn't be much of an app without the root module (which is often named 'app'). The root module is what gets Angular started, with a construct such as:

<div ng-app="myApp"> .... </div> <script> var app = angular.module('myApp', []); </script>

You can think of the root module as a parallel to the main entry point in a .Net program or as the Application_Start in an ASP.Net application. The ng-app directive creates the module and at the same time sets its scope. In the above example, everything within the div is in scope and will be managed by the module, while Angular will not be concerned with any elements outside that div. The signature of the module function is angular.module(name, [dependencies], [configFn]), returning a reference to the new module. The first argument to the angular.module function is the name of the new module, while the second, optional argument is an array of the names of the modules that the module is depending upon - in this example none. If only the first argument is given, the function retrieves a module by name rather than creates it. There is a third optional argument, which is a function to register work which needs to be performed on module loading. That function may itself declare dependencies on various providers. An example:

( function () { var app = angular.module("app", [], ["$locationProvider", ConfigFunction]); function ConfigFunction(locProvider) { locProvider.html5Mode(true); console.log("In configuration function"); } } )();

Using that configuration function parameter is an advanced option and I don't see myself using it any time soon. But now you know it's there.

The Angular docs recommend that you break an application into modules and that each feature and each reusable component (directives, filters etc) be contained in their own module. Exactly what is meant by 'feature' I can't say, I guess it is up to you and depends on the kind of project at hand. The preferred style is to keep the root (app) module thin and factor further components into their own modules. Name a module as you would a namespace, e.g. app.navigation.topmenu for a module which is a child module of a navigation module, which is then a child of the app module. Structuring the modules this way has the benefit of producing chunks that are maintainable and even makes it easier to reuse modules between applications.

Related to the topic of how to modularize an app is the topic of how to structure the code and markup files. You may be used to structure by file type, for example to keep all script files in their own folder. But I would argue that a more sensible (and the recommended) approach is to divide files by feature. This way, files that are related are grouped together. The arrangement of files and folders could even reflect the namespaces used to name modules, which would be nice.

The module object exposes a number of methods and a few properties, of which we have already been using some in this and previous chapters. Rather than giving a complete list of the members I am going to delve on most of the remaining ones in the next chapters. The next chapter will be about using and creating filters - custom filters can be created with a module.filter method.

< Previous chapterNext : Using and creating filters >

2016 by Niels Hede Pedersen Linked in