Getting MEAN: Adding AngularJS

We now have a single page HTML5 application with a CSS styling that enables us to make it look reasonable on any number of devices. It is time to add some functionality and that will be driven mostly by AngularJS.

Creating git branch

As we’ve done in the other sections, first let us create a branch for this step:

lth@ncpws04:~/src/notes$ git branch angular

lth@ncpws04:~/src/notes$ git checkout angular
Switched to branch 'angular'

Installing AngularJS

As all other dependencies we let npm manage our dependencies:

lth@ncpws04:~/src/notes$ npm install angular --save
+ angular@1.6.6
added 1 package in 1.79s

Create the basic application module

We will create our application in the src directory in a file called application.js

Initially we will define our application by creating a new Angular module:

var app = angular.module("notes", []);

We now have an Angular application, so we will need to load Angular itself and this application in our index.html. First add two lines below the place where we loaded the other javascript files:

<script type="text/javascript" src="node_modules/angular/angular.min.js"></script>
<script type="text/javascript" src="application.js"></script>

The final step to make this Angular application run will be to add an attribute to the initial <html> element:

<html ng-app="notes">

What we are doing here is to tell Angular to use the module notes, which was the module we defined in our application.js.

If we try to reload our page now it will look pretty much exactly as it did before and it is not doing much. In fact it is almost impossible to tell that it is running in the first place. In order for us to verify that Angular is actually running, we can add a bit of logging to our Angular module:

app.run(["$log",
    function($log) {
        $log.debug("Angular Application notes is running");
    }
]);

Each Angular module goes through a number of phases and each phase will run certain methods. The first phase each Angular module is going through is a “config” phase. During this phase no other modules – including the logging module – are available. Once the config phase is done for each module, the “run” method is called. At this time the Angular module “$log” is available.

This is also a good time to talk about injection. When browsing the Internet for Angular examples you will often see the above written as:

app.run(
    function($log) {
        $log.debug("Angular Application notes is running");
    }
);

And in our particular case that would work just fine. The problem with that is that often for production sites, you will want to minify the source. As part of that process, variable names are modified, so the above would probably become something like:

app.run(function(a) {a.debug("Angular Application notes is running");

And that would fail because angular don’t know the module “a”. By presenting Angular with an array of Strings with the proper name of each module, the minify process can alter the variable/argument names as it pleases – Angular would still know which modules to inject.

If you load your application in Chrome and showing the Console in the Developer Tools, you will now see:

Add a controller

Angular controllers allows you, as the name suggests, to control a part of your HTML document with a bit of Javascript. Let us define a controller which will control the body tag (and everything inside it):

app.controller("BodyController", ["$log",
    function($log) {
        $log.debug("BodyController: starting");

        var that = this;
        that.angularVersion = angular.version.full;

    }
]);

What this does is that it defines a controller named BodyController, it “injects” the angular module called “$log” into that controller, it logs a statement and then it sets a variable called angularVersion.

This is a good time to explain the somewhat silly variable that. I know I will get a lot of flack about this from “real programmers”. My reasoning is that I don’t fully understand scopes in Javascript. Countless times I have found myself accidentally referencing “this” in a callback function. By setting that = this I can avoid that. If that is unknown, Javascript will tell me so and I can deal with it. The problem is that this is always defined, it might just refer to another this than I suspected.

Now, that we have our controller defined, it is time to use that controller in our html. Modify the body tag, so that it reads:

<body ng-controller="BodyController as bodyCtrl">

What we do here is instruct Angular to run the BodyController and name the BodyController instance: “bodyCtrl”.

Reloading and looking at the Console, it will now look like this:

The bodyCtrl is now available anywhere inside the body element. We can use this in our HTML to interact with the “controller” in what angular call a binding. Bindings are defined using curly brackets. We can now add the following HTML snippet to our index.html:

<p>
  Angular is version {{bodyCtrl.angularVersion}}
</p>

Summary

After this, the index.html in it’s entirety will look like:

<!DOCTYPE html>
<html ng-app="notes">
    <head>
        <title>Notes App</title>

        <link rel="stylesheet" type="text/css" href="node_modules/bootstrap/dist/css/bootstrap.min.css"/>
    </head>
    <body ng-controller="BodyController as bodyCtrl">
        <header class="mb-3">
            <nav class="navbar navbar-dark bg-primary">
                <a class="navbar-brand" href="#">Notes</a>
            </nav>
        </header>

        <div class="container-fluid">
            <p>
                Hello World!
            </p>
            <p>
                Angular is version {{bodyCtrl.angularVersion}}
            </p>
        </div>

        <script type="text/javascript" src="node_modules/jquery/dist/jquery.min.js"></script>
        <script type="text/javascript" src="node_modules/popper.js/dist/umd/popper.min.js"></script>
        <script type="text/javascript" src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
        <script type="text/javascript" src="node_modules/angular/angular.min.js"></script>
        <script type="text/javascript" src="application.js"></script>

    </body>
</html>
<!--+
    | vim: ts=4 et nowrap autoindent
    +-->

And the application.js like this:

/*
 * Angular Application
 */
(function() {

    var app = angular.module("notes", []);

    app.run(["$log",
        function($log) {
            $log.debug("Angular Application notes is running");
        }
    ]);

    app.controller("BodyController", ["$log",
        function($log) {
            $log.debug("BodyController: starting");

            var that = this;
            that.angularVersion = angular.version.full;

        }
    ]);

})();
/*
 * vim: ts=4 et nowrap autoindent
 */

Commit and push to repository

Let’s add our new file and commit our changes:

lth@ncpws04:~/src/notes$ git add *
The following paths are ignored by one of your .gitignore files:
node_modules
Use -f if you really want to add them.
lth@ncpws04:~/src/notes$ git commit -a -m "Added angular"
[angular 8d94ae6] Added angular
 4 files changed, 412 insertions(+), 2 deletions(-)
 create mode 100644 package-lock.json
 create mode 100644 src/application.js
lth@ncpws04:~/src/notes$ git push --set-upstream origin angular
Counting objects: 7, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 4.42 KiB | 0 bytes/s, done.
Total 7 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To github.com:lbthomsen/notes.git
 * [new branch]      angular -> angular
Branch angular set up to track remote branch angular from origin.

 

1 thought on “Getting MEAN: Adding AngularJS

Leave a Comment