Getting Started with Angular JS

Justin Wernick <>
Curly Tail, Curly Braces
2015-06-12

Abstract

Angular JS is quite a popular framework in the web frontend development world at the moment. As a result, a lot of people have been starting to use it. I've been using Angular for a while now, and I'd like to share some information for people who might be starting to use Angular for the first time.

Angular JS

Update 2020-08-22: This article was written in 2015, when there was only one major version of Angular JS. In 2016, a new version of Angular came out (Angular 2, or just "Angular"). This article is specifically talking about Angular JS 1, since that's all that existing at time of writing.

Angular JS is quite a popular framework in the web frontend development world at the moment. As a result, a lot of people have been starting to use it. I've been using Angular for a while now, and I'd like to share some information for people who might be starting to use Angular for the first time.

Angular's Life cycle

I think to understand how to write an Angular app, the first thing you need is a basic understanding of what Angular does, and how it does it.

When you first load up the page, the browser will run through all of your Javascript code. If you're writing an Angular app, this will involve many calls to Angular functions. Most of this, Angular will take note of, but not act on immediately. That's because part of Angular is dependency injection. You can tell it what components are available, but they will only be loaded when they are requested by another component.

After all of the Javascript is run, Angular will look in your HTML for the 'ng-app' tag. This will let Angular know which is the root module of your app (see below for more detail on modules).

Everything inside the ng-app tag is your Angular application. Angular will go through your HTML hierarchy and 'compile' it. This is a fancy way of saying that Angular checks each tag for directives that match it (more on directives below), will call the 'compile' function defined by those directives, and add any template HTML that the directives specify.

Next, Angular will traverse all of the new directives, and call a function defined by the directive called 'link'. In linking, each directive is given a special variable called 'scope'. The scope is a bridge between the HTML templates and the Javascript. The link function is a way for the directive to define new variables on the scope, or register 'watchers'.

Angular is now up and running, waiting for something to happen. Periodically in the background, Angular will go through what it calls a 'digest'. Basically, it will run through all of the variables that directives are watching, and check if they have changed. If they have, Angular will notify that directive, and it can respond to the change. For example, it might be watching the text in an input box. When the text in the input box changes, a callback on a directive will update a label somewhere else on the page.

That's all there is to it. I'm now going to dive into the various components that fit into this life cycle and how to use them.

Modules

All Angular apps have at least one module. You can think of it as an assembled collection of Angular stuff. When you add a third-party library, this will likely define its own modules. When you create your module, you declare which other modules it depends on. Angular will figure out what code to actually run based on which modules are required.

There will be one module that forms the entry point into your app. You let Angular know which module this is by using the ng-app directive (more on directives later).

//Create a new module
var myModule = angular.module('myApp', ['my-dependency']);
<body ng-app="myApp">
</body>

Later on, you'll ask Angular for a reference to your module to add things to it. That looks something like this:

//Retrieve a module
var myModule = angular.module('myApp');

Note the difference between creating a new module and retrieving an existing module.

Services

A service is a reusable chunk of code that you can pass around with dependency injection. For example, you might write a service to perform some calculations, and then pass that service into a directive. Services follow the Singleton design pattern, so be mindful of how you're managing state.

You might also see services referred to as "factories" or "providers". These all fulfill more or less the same purpose, but are injected in slightly different ways. For this example, I'm going to show a factory, since this is the simplest form of service.

//Declare a factory by calling the 'factory' function on a module.
//It takes in an initializer function.
//This function should return an object.
//If you inject myFactory into another service, then the function will
//be called, and the result will be injected into your service.
angular.module('myApp')
       .factory('myFactory', myFactory);

//This function returns an object with the 'foo' function on it.
//This will let other parts of your app call foo to get the string
//'bar'.
//$http is an example of a service built into Angular. When the
//myFactory function is called, $http will be initialized first and
//passed into this function.
function myFactory($http) {
    return {
        foo: function() {
            return 'bar';
        }
    }
}

Directives

Directives are the central concept that everything in Angular is built around. A directive is a reusable component that you use to make elements in your view interactive. If you want to make a date picker, you will be writing a directive. If you want to create a special type of form that makes all of its inputs read only when you click submit, that is also a directive. Angular has many directives built in, and there are many more that you can find in third party libraries, but if you want to make the most of Angular you need to learn to write your own.

<!-- This is how you use a directive that has already been written -->
<div eg-my-directive></div>
//Similar to factories, to declare a directive you need to provide a function.
//This function should return a 'directive definition object', with a set of
//properties that have special names.
angular.module('myApp')
       .directive('egMyDirective', egMyDirective);

//You can do dependency injection into directives.
//In this case, our myFactory factory from earlier will be injected.
function egMyDirective(myFactory) {
    return {
        //'A' stands for Attribute, and this directive is restricted to only be
        //used as an attribute in html. You can also make directives that match
        //on element names or classes, but I find it cleaner to use attributes
        //in most cases.
        restrict: 'A',

        //The URL of your html template. This is optional, but if provided the
        //file will be read and put inside your html element.
        templateUrl: 'egMyDirective.tpl.html',

        //A callback function to the Angular life cycle. This will be called
        //whenever this directive is added to an element to do any custom
        //binding between the directive and the scope.
        link: function(scope, element, attributes) {
            //'message' is added to the scope, so the template can use it
            scope.message = 'Hello world!';

            //This asks Angular to call the provided function if it finds that
            //scope.message has changed during the digest.
            scope.$watch('message', function(newValue) {
                console.log('Message has changed! New value is ' + newValue);
            });
        }
    };
}
<!--This template is put inside the div above-->
<span>
    <!--The curly braces are a shortcut for a common directive that watches the
        specified value on the scope, and updates the value in the view whenever
        it changes. -->
    {{message}}
</span>

Other important topics

Most Angular applications make use of a routing library to control showing different pages when the URL changes. You can do this yourself, but it is easier to use something like the built in ngRoute module. To use this, you will also need to read up on controllers.

Angular makes use of several common Javascript paradigms. You'll find it much easier to understand Angular if you already have a basic understanding of promises and prototype based inheritance.

Angular plays well with Javascript based build tools, such as Grunt and Gulp. Just beware if you're doing minification of Angular code, the dependency injection makes use of the names of the variables to figure out what to inject in. Include ng-annotate into your build process before doing minification and this will solve the problem.

Angular also plays well with unit testing. This works especially well if you have your business logic in a service, since you can just inject your service into the test and check if everything is working. You will want to include the ngMock module in your tests to give you direct control over several of Angular's asynchronous components, like http calls.

Conclusion

This has been a very brief overview of Angular. I'd encourage you to read through the section on Angular's life cycle a few times and do extra research around it. I've found that many other introduction articles want to focus on practical examples, but without that knowledge of what is happening in the background it is very difficult to reason through problems.

I hope you've found this article useful.


If you'd like to share this article on social media, please use this link: https://www.worthe-it.co.za/blog/2015-06-12-getting-started-with-angular-js.html

Copy link to clipboard

Tags: blog, javascript


Support

If you get value from these blog articles, consider supporting me on Patreon. Support via Patreon helps to cover hosting, buying computer stuff, and will allow me to spend more time writing articles and open source software.


Related Articles

An Open/Closed Icon in Angular JS

In this article, I solve the problem of how to toggle an icon between the "open" state and "closed" state on an accordion in Angular JS in three different ways.

WebAssembly

In this article, I explore the opportunity that WebAssembly brings to bridge the gap between native desktop applications and web applications.

Subscribe to my RSS feed.