SJCNet

SJCNet is the home of architect/developer/techie, Simon Coope.

AngularJS Overview

I've been working on some AngularJS projects over the past few months and as a result I've been asked to put together an overview of the core components of the framework to share with colleagues. This post is reproduced here with the permission of my employer Solentive Technology Group.

The Framework

AngularJS is an open source Javascript framework that's developed and maintained by Google. It's a structural framework for creating dynamic web applications and provides such capabilities as data binding and dependency injection.

The core of an Angular application is a module, which is a container for the other components that make up your application (e.g. controllers, directives, services, etc.). The components that make up an Angular application can be split into two groups, "Services" and "Specialised Objects" (as shown below):

Overview Image

In this context, Services are objects that are defined by the developer but using a convention (or recipe) defined by Angular (e.g. Factory, Value, Provider, etc.). Whereas, Specialised Objects are objects that specifically apply to an Angular API (e.g. Controllers, Directives, etc.). So we can say that Specialised Objects are the components that define the structure of an Angular application. Whereas, Services are used by Specialised Objects to perform their operations (e.g. Services can be injected into and used by controllers).

Specialised Objects

As previously mentioned, Specialised Objects apply specifically to the Angular API. The following Specialised Objects are available in Angular.

Controllers

A controller is a JavaScript function that is used to manage and add behaviour to the Angular scope ($scope object). The definitions made on the scope can then be used by an associated template (HTML) to render the web application.

Directives

Directives are objects that are used in the DOM (Document Object Model) of an HTML page. These objects can be elements, attributes, class names or even comments, and are used in Angular to attach additional functionality or behaviour to the DOM.

For example, we could have a directive that is represented in the HTML as an element and is used to render a list of elements used to capture a user’s address. When the page is processed Angular replaces (or appends to) the pointer element in the DOM with the compiled template created in the directive.

Directives are at the heart of all work in Angular and can be the most complicated piece of Angular to understand.

Filters

Filters are used to apply formatting to an expression for display and can be used in templates, controllers or services. Furthermore, you can also create custom filters.

Animations

Animations are pointers that can be applied to directives to trigger animations (using CSS transitions) during the lifecycle of an application. For example, we can attach an animation to the ngView directive that causes the content to slide into place each time a new view is loaded.

Services

Services are objects that are created by the developer, but following conventions (the Angular documentation uses the term "recipes") defined by the framework. The following Services are available for use.

Provider

The provider is the core type of service, as all other services are simply adaptations of it. Therefore, the provider is the most verbose type with the most functionality.

The provider type is basically a custom type that implements a $get method. So we could create a provider as follows:

angular.module('app').provider('providerName',
    function TestProvider() {
        var setting = 10;

        this.setting = function (value) {
            setting = value;
        };

        this.$get = ['dependency1',
            function factory(dependency1) {

                function Ctor() {
                    if (setting > 0) {
                        // Do something
                    }
                }

                return Ctor;
            }];
    }
);

When supplying a provider as an injectable argument the constructor argument you are actually supplied with is the result of calling the ProviderName.$get method. The actual constructor function of the provider is run before the $get method is called so in the above example the setting value would be set before the $get method runs and can be used in the initializion of the object returned from the $get method.

Providers have the benefit that they can be configured during the module configuration phase, and as such you should only use the Provider type to expose application-wide configuration that must be made before the application starts. For example:

angular.module('app').config(
['providerNameProvider'],
    function (providerNameProvider) {
        providerNameProvider.setting(10);
    }
);

Value

The value type is the most basic type of provider and is used to provide a value representation (e.g. string, integer, etc.) for a given key. It's a way of adding variables to the main application module. However a value service cannot have dependencies and has no concept of initialization.

angular.module('app').value('Id', 'ABC1234');

Factory

The factory service type offers more functionality than the value type, mainly by virtue of the fact that factories can have dependencies (i.e. other services can be injected) and has an initialization.

Factories are constructed using a function that can have zero or many arguments which then become the factory's dependencies (e.g. other services). The return value of this constructor function is the instance of the factory.

angular.module('app').factory('FactoryName',
    ['dependency1',
        function (dependency1) {

            function Ctor() {
                // Do something...
            }

            return Ctor;
        }
    ]
);

When injecting a factory as a dependency into another object (either Specialised Object or Service) the factory argument passed to the object's constructor will be a factory service type which can be used to construct an instance of the factory service, for example:

var factory = new FactoryName();

Service

Despite the service service type being confusingly named like it's parent type (I'll call it service recipe from now), it is basically the same as the factory service type and can be constructed as follows:

angular.module('app').service('FactoryName',
    ['dependency1',
        function (dependency1) {

            function Ctor() {
                // Do something...
            }

            return Ctor;
        }
    ]
);

However, the service recipe is different from a factory in that it's constructor is automatically invoked with the new operator when the recipe is used. So if we inject a service recipe as a dependency into another object the service recipe argument passed into the objects constructor will already have been initialized and hence we don't need to manually use the new operator as with a factory type/recipe.

Constant

The constant service type is used to provide simple values that can be used in the module configuration and run phases. For example, we could declare the following constant:

angular.module('app').constant('setting1', 10);

Then in the configuration phase (when other services aren't available) we can use the constant:

angular.module('app').config(
    ['providerNameProvider', 'setting1'],
    function (providerNameProvider, setting1) {
    	providerNameProvider.setting(setting1);
    }
);

We could also use the constant at run time by injecting it into controllers, etc.

Conclusions

This has been a very brief overview of the core components of the AngularJS framework, which I hope will be of use to people who are new to Angular.

Please feel free to comment...

Author image
About Simon Coope
Sydney, Australia Website
Experienced developer/consultant. Loves all things development, technology, gadgets, football and running.