Software development

Tech Pick of the Week: AngularJS

Topics
Coding, Javascript, Tech Pick of the Week, Web Development

You’ve probably heard about AngularJS, right? It’s hard not to run into it if you do web front-end development, especially when building rich single-page apps. Just have a look at what Google Trends has to say about this: AngularJS is currently pretty much the hottest Javascript framework or library out there (although jQuery has far more searches on Google, we won’t consider it “hot”). There seems to be something appealing about AngularJS. But is it just “yet another Javascript framework”, or is there something unique to it? In this post I want to point out some important aspects of AngularJS which make it stand out.

Separation of concerns: App Structure

For non-trivial projects, it’s crucial to have a code base that allows you to extend and change the product without affecting its reliability. If you’re not careful, you may end up with spaghetti code and too much interdependence between components during the code’s growth phase. Of course, this is rarely a flaw of the underlying framework, but rather a lack of discipline or expertise from the developers. After working on a bunch of projects, however, one quickly realizes that even excellent developers fail with respect to this, especially if things have to be done in a rush or if the code base that they have to work with already suffers from these issues.

AngularJS has some strong opinions on how to split up your application. Typical AngularJS apps are composed of these building blocks:

  1. Directives
  2. Controllers
  3. Services
  4. Filters

It’s true, there is no “Model” and no “View” here, but AngularJS still implements Model-View-Controller best practices by clearly separating data, presentation and interaction, and allowing a very loose coupling of these components. I am going to show you how MVC is implemented in AngularJS (even though there are no classes with the explicit names "Model" and "View").

The Data Layer: Models

The Data or Model layer are simple Javascript objects. For example, this could be the data of a user entity:

user = { firstName: "Foo", lastName: "Bar" };

No methods are needed at all to make this usable in the Controller and View Layers – plain Javascript objects are all you need. To make it a Model in AngularJS, you have to assign this data to a scope. Most often this will be the scope of a Controller.

The Interaction Layer: Controllers

Assigning some data to a Controller's scope is straight forward:

function LoginController($scope) {
    $scope.user = {
        firstName: "Foo",
        lastName: "Bar"
    };
}

This way you link a Controller to a Model. AngularJS makes heavy use of dependency injection to allow loose coupling. All dependencies of the Controller (or any other of the aforementioned building blocks) have to be injected into it. AngularJS takes care of registering your Components with the dependency injection system, making it easy to use and avoids polluting the global scope.

Often you need to get data from a web service or a browser’s offline storage. That’s where services come into play, but we will not cover them in detail in this introduction. Basically, you would just call a method of an injected service to fill your scope with data.

As you would expect, Controllers also take care of the business logic of an associated View:

function LoginController($scope) {
    $scope.user = {
        firstName: "Foo",
        lastName: "Bar"
    };

    $scope.login = function () {
      // do things to log in user
    }
}

We defined a login method on the scope that is, for example, triggered when the user clicks a button. Let’s see how we wire things up in the presentation layer.

The Presentation Layer: Views

In AngularJS, the View is simply the DOM. You build your presentation layer with HTML. I don’t expect you to be too enthusiastic about this fact, but far more interesting is how you bind data to your views:

<div ng-controller="LoginController">
  <span>Hello {{ user.firstName }}</span>
  <input ng-model="user.firstName"></span>
</div>

The actual data binding happens in the curly braces. This expression will be replaced by the value of user.firstName. The input field is also linked to the data model via the ng-model directive. Because of two-way databinding, changing the input’s value will immediately update the data model and the representation in the view (check it out live here).

Also notice the surrounding div and its attribute ng-controller. This is an AngularJS directive that binds the corresponding scope of the Controller to the HTML tag and its children. Because of this directive, the scope variables can be accessed in the view.
The direct declarative data-binding in HTML and the automagic updates from two-way data-binding is quite handy already. But the real power and uniqueness of AngularJS views comes from Directives, which we will cover next.

Superpowers for the View: Directives

Directives are, for sure, the most unique aspect of AngularJS: AngularJS hooks into the DOM compilation of a page and matches HTML tags against known directives. This is how data-binding and binding Controller methods to DOM events happens.

In many cases, this makes error-prone DOM manipulations obsolete and allows to express your data representation in the view directly, where it actually should belong. This declarative approach separates the presentation logic from other components:

<div ng-repeat="login in logins">{{ login }}</div>

Using the ng-repeat directive, this will put a div for every element in the logins array which will have the corresponding element as its text content.

Whenever the logins model changes, this will automatically update the DOM. You don't have to create, remove or update the DOM yourself (as you would often do in other frameworks). In fact, AngularJS Controllers should never touch the DOM directly, but only update models. These changes will then migrate to the view automatically.

But Directives are even more powerful: they allow you to extend HTML to make it a rich domain-specific language for building your application. To do so, you can create your very own directives. These custom directives can be any kind of UI component you would need. For example, you can build an image viewer as a directive and use it like this:

<div ng-model="images" my-image-viewer></div>

This simple HTML snippet would be transformed in a full-blown image viewer that is used to browse through all the images of the model. This would include the whole UI and its logic. The best thing is, due to very good encapsulation, it's a truly reusable component. It’s easy to move it around and put it to different places without having to touch DOM manipulation code, which can easily break and is hard to test.

Directives are extremely powerful and are (in my opinion) the feature that makes AngularJS really stand out. How to create your own directives is worth its own post, so I won't cover that here.

Conclusion

So, why is AngularJS so special? Of course it’s possible to create robust and clean applications with any other framework (or even without a framework), but AngularJS has a very nice architecture that facilitates good practices in the following ways:

  • Separation of Concerns, following a MVC pattern
  • Loose coupling through dependency injection
  • Reusable, declarative UI Components

These practices – dependency injection in particular – also make AngularJS testing very natural. Since you have to inject all dependencies anyways, it's very easy to stub anything you want.

Directives might be the only thing that is truly unique to AngularJS, but combined with the excellent architectural choices, AngularJS really stands out as a powerful and robust one-stop solution for you Javascript application.

If you want to get your hands on some code, check out this JSFiddle.