Getting Started with Angular (Modules, Controllers, oh My)

I have started studying Angular framework a few weeks ago.  I always try to keep up with frameworks out there in the world to see if any of them can save me time and fill in specific needs for my projects.  I was attracted by apparent simplicity of Angular, judging by few demos I viewed.  Once I started using on a real project I quickly ran into  situation where my knowledge of Angular clearly lacked.  Hence, I am writing this post to help me untangle my thoughts and clarify the application structure in my head.

Here is the use case.  I have an application.  I would like to separate into modules, each consisting of one or more controllers.  Controllers, IMHO, are at heart of Angular, playing similar role to ViewModels’ methods of Knockout.  There is one bid difference though.  Angular uses data binding based on $scope object that is the root of object structure that is bound to controls.  In this small example I want to create an app called myApp with one module called user with one controller – login controller.  let’s get started.

I am going to put my app into a single JavaScript file called app.js.  There is only one line of code in it, creating my app, which is also a module.

var myApp = angular.module('myApp', ["myApp.user"]);

Let’s break it down.  I am creating the only global variable my application will have – my main app object. I am calling Angular’s module function, passing in module name.  The next parameter is an array of dependencies, in my case modules my app will depend on.  So far I only have one module – myApp.users.  Event though the name is just a string, I like dotted syntax – it helps me think hieratically.

Let’s take a look at users module next.

 

angular.module("myApp.user", ["utilitiesService"])
       .controller("loginController", ["$scope", "$http", "utilities", function ($scope, $http, utilities) {
           $scope.login = function () {
               utilities.showPleaseWait();
               $http.post(myApp.rootUrl + 'Login/ProcessLogon', { userName: $scope.userName, password: $scope.password }).success(function (data) {
                   utilities.hidePleaseWait();
                   //handle success, check result
               }).error(function (data) {
                   utilities.hidePleaseWait();
                   alert('Communication error');
               });
           };
       }]);

Let’s break down the module.  Again, you see module call.  This time I have one dependency – on utilitiesService.  It is unimportant to what it does in our case, but essentially it is just a group of methods most screens will use.  Then I create controller factory method.  There is an important distinction here.  All objects are created lazily in Angular, only when they are needed.  Hence, my function that sets up controller (the last parameter to controller() method call) is only called when I mention loginContoller in my html.  More on that later.  You see $scope as one of the parameters – I just need to add properties and methods to it that I will bind in my UI.  I am adding one method – login method.

Now, let’s look at the HTML of the view bound to login controller

<div class="row" data-ng-controller="loginController">
    <div class="span4 offset4">
        <div class="well">
            <legend>Login</legend>
            <form data-ng-submit="login()" method="POST">
                <label>User Name</label>
                <input class="span3" placeholder="Enter email address" type="text" name="userName" required data-ng-model="userEmail">
                <label>Password</label>
                <input class="span3" placeholder="Enter your password" type="password" name="password" required data-ng-model="password">
                <button class="btn-info btn">Login</button>
            </form>
        </div>
    </div>
</div>

You probably noticed that I did not have to add userName and password properties to $scope in my controller.  Angular will just create them itself.  I would have added them, but I had no default values for them, so I did not see a point in that.  You see ng-controller directive – Angular will find loginContoller and bind to it to the view.  You see a few field bindings – those are ng-model directives.  You also see ng-submit.  This directive will handle form submission.  I could have used ng-click on the button instead.  login() method in that directive will call login function of the loginController  you saw above.

Now, the lest step is to inject the actual application.  I did so on html tag of my shell view.  Since I am using ASP.NET MVC, I actually did so in _Layout.cshtml.  Again, this is a hybrid app, and you can inject main app any which way you like.

<!DOCTYPE html>
<html data-ng-app="myApp">

 

That is it.  This completes the circle by injecting my app into html by using ng-app directive and giving it the module I created as my main app.

To summarize, you can create your central app object by creating a new module.  In that declaration you can supply all the modules your app depends on.  Then you can create those dependent module and create their controllers within module() / controller() call chains.  There is one big advantage of this approach over what you see in demos.  In most demos all controllers are global.  If you structure your app as above, you only have one global object – your main app object.

On a side note, prefixing ng- directives with data- is my personal choice.  It keeps Visual Studio from complaining about invalid html.  You can just use ng-.

Thanks and enjoy.

2 Comments

  1. Nice post Sergey. Angular is a great looking frame work. Since you’re looking at Angular, did you also give any attention to Durandal.js? It fills in some of the conceptual gaps that knockout wasn’t meant to address (although for now it uses knockout for binding) while giving us a familiar View Model concept (e.g. View/Viewmodel mapping, page lifecycle, routing, eventing, etc.). If you haven’t looked at it, I’d like your thoughts on it if/when you get a chance to look at it!

  2. I have seen Durandal as part of knockout course on Pluralsight. One thing that attracted me to Angular is that you do not need to add more plugins to it to build SPA. Then again, at the end the framework does not matter as much. I believe most of them accomplish pretty much the same set of tasks.

Leave a Reply

Your email address will not be published. Required fields are marked *