Angular Tutorial – Part 2: Understanding Modules and Controllers

In this article we will try to understand and implement modules and controller in Angular.js. We will start with angular module and see why and how it is useful. We will then define a simple angular module for a test application. Next we will look at the concept of controllers in angular and try to implement a simple controller to understand the concepts. We will also look at the JavaScript design pattern called IIFE (Immediately Invoked Function Expression) as it is a very useful pattern to avoid globals when creating angular applications.


Link to complete series

  1. Angular Tutorial – Part 1: Introduction to Angular.js
  2. Angular Tutorial – Part 2: Understanding Modules and Controllers
  3. Angular Tutorial – Part 3: Understanding and using Directives
  4. Angular Tutorial – Part 4: Understanding and implementing Filters
  5. Angular Tutorial – Part 5: Understanding and implementing Services
  6. Angular Tutorial – Part 6: Building and Validating Data Entry Forms
  7. Angular Tutorial – Part 7: Understanding Single page applications and Angular routing

Background

In the previous article of this series we looked at why Angular.js is in vogue and how it JavaScript frameworks can help in creating client side code Single page applications in a structured manner. We also looked at a small sample where we tried to write the “Hello World” sample in Angular.js. We created a simple module, controller and placed some directives on our view to create our sample. In this article, we will dive into the details of the angular modules and controllers and in the next article we will look at the significance of directives in details.

Modules in Angular.Js

Let us start the discussion with the angular modules. Modules in angular can be thought of as a container where all the other parts of our application like controllers, services and directives will be contained in. We have been using the word module in software development as a logical piece of application that can be developed independently of other modules and which can be used/reused by other modules. Angular has literally taken this concept for angular modules. If we could think of a logical piece of functionality that contains tightly coupled components(controllers, services, directives and filters) then we can pack them as an angular module.

For small applications, perhaps one module is enough. In this case the module can be thought of as something that defines our application. For larger applications, we might need to create multiple modules. The best part about module is that a module can easily be passed to another module and its functionality can easily be used by other modules.

Lets see how we can create a simple module in angular. Typically we create a separate .js file and define our module in it. This file will be responsible for creating the configuring the module for our application.

angular2_1

In the above image, I have created a simple website with only index.html. We are using the domain style to organize our code. I have also added the angular.js file in the libs folder. Let us now create an app.js file in the app folder and include angular and our app.js reference in the index.html.

angular2_2

Now that we have a structure in place, let us start creating an angular module. To create a module, we need to use the angular.module function. Lets create a simple module named “ myAngularApplication”.

What the above code will do it that, it will create an angular module with the name of “ myAngularApplication”. Most people often ask what is the significance of the empty array that we are passing as a second argument. Remember we talked about modules being able to use other modules. The second array argument is to pass the dependencies to other modules. So lets say we have another module called “ myAnotherApplication” which would want to use the above defined module. We will have to pass the myAngularApplicationin the array argument as shown in the following code.

We can pass any number of modules in this array and it will enable the other modules to access the passed(injected) modules from within the module components.

Now here is an interesting part, if we forget to pass the second array argument, it will change the meaning of our code completely. The function with 2 arguments i.e. the one with second argument as an array(empty or otherwise) is a setter function. It will create an angular module for us. Where as if we omit the second array argument, the function is a getter function i.e. it will return the module that is created with the name passed. So its important to understand this subtle but very important difference.

  • Module Setter: var myModule = angular.module('myAngularApplication', []);
  • Module Getter: var myModule = angular.module('myAngularApplication');

Now once we have the module defined, we will have to create all the components inside of this module. we will use a code like myModule.controller(........)to create controllers inside this module. The other components are also created with modules in a similar manner.

Last but not the least, if we want any view to use this angular module, we need to put the ng-app="myAngularApplication" in that view. Lets do that in the HTML tag of our index page so that the complete page will have access to this angular module.

angular2_3

Now that we are all set with our application created, how can we quickly check whether what we did is working or not. We can test our application by writting a simple angular expression inside our HTML body. An expression is the angular’s way to putting JavaScript code embedded inside the HTML views. Expressions can be put on views using double curly braces as {{ }}. To to test our application, lets put {{ 2 + 2 }} in our body. It we open the HTML and see 4 on the page, we can assure that the angular module is created and is now working. If not, we will get error on the browser console.

Controllers in Angular.Js

Now that we have our module ready, lets move our focus to the controller. In simple words controller is a JavaScript object that let us control the data that is to be rendered on the views. It also let us handle the data coming from the views and act upon it based on the application requirements. Behind every view, there is a controller which takes care of all the core business logic and is responsible to control the flow of data in the application.

The way angular facilitate the control of view data via the controller class is by a magical object called $scope. $scope itself is a very vast topic this is definetly not the time to start talking about scope of $scope and its details like inheritance. We will discuss the details of $scope in a later article but for now lets thing of $scope as an object that is shared between the controller and the view. We can think of it as a common box where the view and controller will put all their belongings and perhaps pick up the required one whenever needed.

angular2_4

Now that we know the basic definition and purpose of controller and $scope, lets define a simple controller in our application. Lets create a controller that will show the list of books on the view. Lets call it a booksController. Since we are using the domain style for organization, lets first add the .js file for the booksControlleri.e. booksController.js. Lets add the reference to this file in our index.html after the app.js.

angular2_5

Now that we have setup our code, lets see how we can create a controller function. A controller is a simple function that we need to create on the angular module object. Now since we already have the module created and assigned in a global variable myModule, lets create our controller function on that only.

In the above code we are first creating a function named booksController. we will use this function as our controller class and this we are passing the instance of $scope. Then we are associating this function with our module using the myModule.controller function. Once this is done, our controller class is ready to be used with the view.

Note: The code that we just wrote is mainly for explanation. There are few issues with it which I will talk in a moment when we will discuss the minification safety and IIFE in next section.

Now that we have our controller ready, lets see how we can attach it to a view. To associate a controller with a view we need to use ng-controller attribute on the html element where we want to use this controller. Lets add the ng-controller on the body element of the view. Also, since we know that the controller is adding a property on $scope object called message, we can use angular expression to access this property.

angular2_6

Now with this code if we run the application, we can see the message being passed from controller to the view using the $scopeobject.

angular2_7

Note: We have talked about one way and two way binding a little in previous article and we will talk about it in detail in later article but for now using the angular expression in view to access the controller property is enough.

Writing more robust code

We have created our first angular module and controller. Are we ready to get started with some serious angular development. The answer to this question is both yes and no. Yes because we have understood the concepts involved behind the module and controller. and No because our code is not good from a best practices perspective and believe it or not it will not even work if we minify this code and start using it. Lets see what problems we have and how can we solve them.

Understanding IIFE (Immediately Invoked Function Expression)

So far we have been using the free code to create our angular module. The main reason for this was that we wanted our code to get executed as soon as the file is loaded. We are also putting our created module in a global variable which is also not a good idea. So lets see how we can fix these issues by the help of IIFEs.

First lets move our free code into a function and then call this function. This will effectively be same as our current code.

Next instead of explicitly calling this function why not call the function at its definition itself. This can be done in the following manner.

Now since no one else will be calling this function as we are calling it at the definition itself, we can do away with the function name too. The resulting code will look like following.

This expression above is known as Immediately invoked function expression(IIFE). Since the function definition will immediately invoke itself whenever the .js file is loaded.

The main reason the IIFE is effective is that we can have all the code immediately executing without needing to have global variables and functions. We still have the myModulevariable declared as global so lets do away with it too.

Now when we do this, our controller creation will fail as we were using the global variable to create controller with the module. To circumvent this problem lets use the getter function angular.module to associate the controller with the module. And while we are at it, why not put the controller in an IIFE too.

Making our controllers minification safe

Now our controller and module are looking good and we are not using any global variables. Now when we are ready to push this code into production, we will first minify the code and then send it to production(for various optimization and other reasons). What minification will do is that it will change shorten the variable names. Which would mean that the $scope that we are passing to the booksControllerwill no longer be $scope but some short variable name.

The problem here is that the angular is still expecting a $scope variable to wire up the controller to view data passing. But the $scope variable is not present in the minified file and thus resulting in the errors. Same problem will come with all the parameters that are being injected into controller function. So we need some way to indicate the angular that the variable that is being passed to the controller is in fact a $scope so that it can be used after minification too.

To do this, we need to write our controller creation code a little differently. What we need to do is to pass the second argument as array where we can put the controller arguments as string literals. The resulting controller code will look like following.

On the same lines, we can pass all the controller parameters as string literals in this function call and the angular will know that even after minification how these parameters should be treated.

Using the controller as syntax

Before we end this article, let us also look at an alternate way of passing data from controller to view. If our controller has some member variable defined that is not attached to scope that can be accessed from the view by using controller as syntax. Lets say our controller has a property greeting defined as.

If we want to access this property from view we can use the controller as syntax as shown below.

angular2_8

Note: The benefit of using this approach is that our code is decoupled from the $scope object. Comparing $scope vs controller as syntax could be a little confusing at this stage so lets do that in a later article and keep this article free from digression.

Using the code

Lets not end this article without writing a substantial functionality. Lets change our controller to keep track of a list of books and our view will show this list of books. Lets define an array of books on the $scope which will initially be empty. We will then create a function fetchBookswhich will populate this list with some dummy books data. In real world applications, this data will be retrieved from the server. Lets now look at the controller code with these changes.

Now on the view part. I have added a little bootstrap to the view to make it look pretty so the view code now looks like following.

angular2_9

Except for the bootstrap classes, what we have done here is that we have created a button that is calling the fetchBooksfunction on ng-click directive. ng-click directive can be associated with the HTML elements and act on click event to invoke a controller function.

Below that we have a table that is rendering rows using ng-repeat directive. ng-repeatis a directive that can iterate over items of a collection and render the specified html elements for all the items. We are rendering row for each book in the books collection.

When we run the code and look click on the fetch button we can see the result on screen as:

angular2_10

Note: We will look at the ng-click and ng-repeat directives in details in further articles, here we are just giving a sneak peak to see how things get wired up and how easily we got our view to render the list of books.

And now we have a basic angular application ready that is capable of rendering a list of hard coded books.

Point of interest

In this article we looked at the concept of modules and controllers in angular. We looked at how we can use IIFEs to better manage our code and how to make our controllers minification safe. This has been written from a beginners perspective and I hope this has been informative.

Download sample code for this article: SampleApp2