Developing SPAs using Angular.js

Ilitumwa mnamo - Iliwekwa upya mnamo

We can divide JavaScript Frameworks into three big groups, server side JavaScript frameworks (like node.js), DOM Manipulation frameworks (like jQuery) and MVC frameworks, like Angular. Angular, initially was developed by Google and is one of the most widely adopted JavaScript MVC Frameworks.

What is an SPA?

Single Page Applications are webpages, which load their content dynamically and provide a fluid and seamless user experience, avoid full page loads and manipulate the html page structure to display and update data. SPAs can help to reduce the network traffic, because once all the necessary sources from the server are loaded and there is no page reload the only traffic between the client and server comes from data manipulation.

Angular.js

Angular is data-driven and is perfect for creating SPAs, where the data has to go in two directions, from client to server and server to client. It has four basic building blocks:

  1. Filters are transforming data between the Model and the View, it is important to note, these only change how the data is displayed and don’t change the underlying model. (Angular has filters like currency, number, orderBy, lowercase, uppercase).
  2. Factories usually are used to maintain a single instance of data or state of the application, in many cases they provide an abstraction layer between directives and API calls.
  3. Directives are packaged functionalities which can be dropped anywhere in the application. The mostly used directive is ng-model, ng-click, ng-show, ng-hide and ng-repeat.
  4. Controllers are similar to directives the main difference compared to Directives is that Directives contain extra templating.

The JavaScript code

The Angular applications have two building blocks, the HTML page with the declared Angular directives, filters, bindings and the JavaScript code, which is executed by the browser.

var contactCardsApp = angular.module('contactCardsApp', []);
contactCardsApp.controller('ContactListCtrl', ['$scope', '$http',function ($scope, $http) {
    $scope.contacts = [];
   ...
}]);

First I create a new Angular module with the name contactCardsApp. For this module I create a controller. A module can contain many controllers, but for the sample application I will only use one controller. When creating the controller, it is important to assign a unique name to it.

The second parameter for the controller is an array (in other, simple cases this does not have to be an array), where I enumerate all the dependent services (angular will cover the Dependency Injection for me). For the sample application I need $scope and $http services. The $scope is always needed for the Angular application. The $http service has to be added because I want to load the data using GET requests.

  $http.get('/api/contacts')
        .success(function (response) {
            $scope.contacts = response;
        })
        .error(function (error) {
            console.log(error);
            alert(error);
        });

To invoke the $http.get() method, I need to pass in the URL and define a success() and an error() method. In case of a successful load I set the $scope.contacts variable to the response object (if the response type is JSON, Angular will be able to handle it, no data conversion is needed). In case of an error, I log the error message to the console and show it to the user using alert.

To filter the data I created a custom filter, I will use it in the HTML code later. I register the filter as a function on the application $scope. The filter is checking if the contact object has the MobilePhone number set or not. If the property is not set, it will skip the item.

 $scope.mobileFilter = function (contact) {
        if (contact.MobilePhone === null || contact.MobilePhone === undefined) {
            return false;
        }
        return true;
    };

The HTML Markup

In the html code I mark a div element as an Angular application using the ng-app attribute (which, behind the scenes points to the ngApp directive). Usually this is set on the root HTML element (<html>) but now I set it on a div element to demonstrate this can change, depending on the needs.

<div ng-app="contactCardsApp">
    <div class="row" ng-controller="ContactListCtrl">
        <h2>SPA using Angular.js</h2>

        <h3>In total there are {{ contacts.length }} contacts, the ones without Mobile Phone number were excluded.</h3>

        <div class="panel callout radius" ng-repeat="contact in contacts | filter: mobileFilter">
            <h4>{{contact.FirstName}} {{contact.LastName | uppercase}}</h4>
            <p>
                <span class="round success label">Website: {{contact.Website}}</span>
                <br/>
                <span class="round success label">Email: {{contact.Email}}</span>
                <br />
                <span class="round success label">Mobile: {{contact.MobilePhone }}</span>
            </p>
            <span class="radius secondary label">ID:{{contact.ID}}</span>
        </div>
    </div>
</div>

Inside the ng-app, I create a div, where I assign the controller. There I use the name of the controller (this is why it’s important to have unique names for controllers, so angular can exactly identify those).

Angular’s template engine has similar syntax and conventions with other templating engines, for example object properties can be displayed using {{ object.property }} format.

The div marked with ng-repeat directive is where all the logic happens. Angular iterates over the JSON objects in the contacts array (this was set in $http.get().success() method). It invokes the mobileFilter for the items, if the filter returns a true value then it creates a new div element where the template engine evaluates the {{ object.property }} constructs using the contact object and displays FirstName, LastName, Website, Email, MobilePhone.

 <div class="panel callout radius" ng-repeat="contact in contacts | filter: mobileFilter">
           ...
 </div>

For the LastName I apply another filter, uppercase, this will transform the text in the property to be uppercase.

The sample Angular application has the below output:

Angular SPA

The code can be found on GitHub. Look under Scripts/spa/contactCards.js and Views/Home/Angular.cshtml

Ametuma 13 Februari, 2015

Greg Bogdan

Software Engineer, Blogger, Tech Enthusiast

I am a Software Engineer with over 7 years of experience in different domains(ERP, Financial Products and Alerting Systems). My main expertise is .NET, Java, Python and JavaScript. I like technical writing and have good experience in creating tutorials and how to technical articles. I am passionate about technology and I love what I do and I always intend to 100% fulfill the project which I am ...

Nakala Mpya

Advanced jQuery