OdeToCode IC Logo

AngularJS Abstractions: Services

Wednesday, June 5, 2013 by K. Scott Allen

At first glance, services in AngularJS are a catch-all destination for any code that doesn’t fall into one of the other primary abstractions in the framework. If it’s not a controller, filter, directive, or model,  it must be a service. One reason to think to think this way is because one can interpret the word “service” to mean anything in software. However, services in Angular have capabilities and behaviors that make them well suited for specific jobs.

Services As Application Helpers

Controllers, applications, and even other services can take a dependency on 0 or more services, meaning services can be a convenient location for code that is used in different places throughout an application. For example, if two controllers both require some algorithmic logic to make a decision, it would be better to place the logic inside a service that both controllers can use than have the code duplicated in two different controllers.

Services As Singletons

AngularJS will manage services to make sure there is only one instance of a service per application. This makes services a convenient storage location for data that needs to stick around (controllers and their models can come and go as views are loaded and unloaded in the DOM).

Services As Communication Hubs

AngularJS provides a framework to achieve a separation of concerns and a the various components have no knowledge of each other. Since services can be injected into almost anything (controllers, directives, filters, and even other services), a service can play the role of a mediator or event aggregator for other components to communicate in a loosely coupled manner.

Services As Injectable Dependencies

Perhaps the biggest reason to put code into a service is because services are injected into other components, meaning components maintain a loose coupling and any particular service can be replaced during a unit test. AngularJS itself provides many services that fall into this category. There is the $http service (for network communication),  the $window service (a wrapper for the global window object), the $log service, and others.

What Isn’t A Service?

There is plenty of vanilla JavaScript code you can write for an AngularJS application that doesn’t have to live inside an AngularJS abstraction. Model and view model definitions, for example, could live outside of any controller or service. Controllers could instantiate models, obviously, and services could hold references and vice versa. My candidates for services generally fall into one of the previous 4 categories, and as models are easy to test without test doubles, they don’t need to be injected and hence don’t need to be considered a service themselves, although it is certainly reasonable to make a service responsible for fetching a model from some unknown data source.

How To Create A Service?

One of the confusing areas of AngularJS revolves around the APIs for  creating a service, since there are no fewer than 6 ways to register a service and the obvious API choice, a method named service, probably shouldn’t be your first choice. The one that can adapt to just about any scenario is the factory method, which when used on a module object looks like something that would define a factory function for the module, but in fact is defining a factory function for a service (another unfortunate point of confusion).

As an example, here is a service to wrap the geolocation APIs of  the browser:

(function () {

    var geo = function ($q, $rootScope) {

        var apply = function () {
            $rootScope.$apply();
        };

        var locate = function () {
            var defer = $q.defer(); 
            navigator.geolocation.getCurrentPosition(
                function (position) {
                    defer.resolve(position);
                    apply();
                },
                function(error) {
                    defer.reject(error);
                    apply();
                });
            return defer.promise;
        };

        return {
            locate: locate
        };
    };

    geo.$inject = ["$q", "$rootScope"];

    angular.module("testApp")
           .factory("geo", geo);

}());

The factory method takes a function that AngularJS will invoke to create the service instance. This geo service makes use of the $q service provided by Angular to create promises for the asynchronous delivery of latitude and longitude. Somewhere else in the app, a controller can take a dependency on the geo service and use it to find the user’s position.

(function () {

    var TestController = function ($scope, geo) {

        geo.locate()
           .then(function (position) {
                $scope.position = position;
            });
    };

    TestController.$inject = ["$scope", "geo"];

    angular.module("testApp")
           .controller("TestController", TestController);

}());

Summary

Services are an important part of any AngularJS application. The built-in services in the framework make code more testable, and custom services can provide an abstraction to make code easier to maintain.

AngularJS Abstractions: Directives

Tuesday, May 28, 2013 by K. Scott Allen

Directives are one of the lynchpins that make AngularJS work, and also make the framework nice to work with.

Directives are the attributes Angular searches for in the markup when the DOM is loaded, attributes like ng-app, ng-controller, and ng-click. You can also use directives to create custom elements, like <my-widget>, but doing so depends on how much value you place in having your raw source validated by an HTML validator.

If validation is high on your list, there are HTML 5 compliant approaches to using directives, including data- prefixing attribute directives (use data-ng-controller instead of ng-controller, for example, and Angular still works).

What Are They Really?

From an abstraction perspective, directives form an anti-corruption layer between a model and a view. Directives are where you can listen for changes in a model value and then go manipulate the DOM. Directives allow models to change the content and presentation of a view without the model getting bogged down by the DOM manipulation code. The model stays clean, testable, and plain.

Here’s an example of a custom “myShow” directive(note that AngularJS already has an ngShow directive to do this job, but this is an easy example to understand).

The purpose of the myShow attribute is to show or hide a DOM element based on the truthiness of a model value.

First, the markup:

<div data-ng-controller="TestController">
    
    <div data-my-show="model.visible">
        {{model.message}}
    </div>
            
    <button data-ng-click="model.toggleVisible()">Click me!</button>

</div>

Notice the data-my-show attribute on the first inner div. The attribute value is set to “model.visible”.

Here is the controller and model for the scenario:

(function () {

    var model = {
        visible: false,
        message: "Surprise!",
        toggleVisible: function () {
            this.visible = !this.visible;
        }
    };

    var TestController = function ($scope) {
        $scope.model = model;
    };

    TestController.$inject = ["$scope"];

    angular.module("testApp")
           .controller("TestController", TestController);

}());

All that’s needed now is the code for the my-show directive:

(function () {

    var myShow = function() {
        return {
            restrict: "A",
            link: function(scope, element, attrs) {
                scope.$watch(attrs.myShow, function(value) {
                    element.css("display", value ? "" : "none");
                });
            }
        };
    };

    angular.module("testApp")
           .directive("myShow", myShow);
}());

The naming conventions applied by AngularJS allow the directive registered as “myShow” to be applied in markup as data-my-show, as well as my-show and a few other variations. 

The directive itself is setup by a function that returns a “directive definition object” (let’s call it the DDO). The DDO has to have a few members in place for the directive to work, but this sample only uses a couple members: restrict and link.

The restrict property specifies where the directive is valid (E for element, A for attribute, C for class, M for comment). Since the default for restrict is “A”, this property could be omitted.

The link function is responsible for making things happen by setting up watches to listen for changes in the model.  Angular invokes the link function and gives it the model (scope), the element (effectively a jQuery wrapped reference to the DOM element), and an attrs parameter containing the attributes of the element. Asking for attrs.myShow will return “model.visible”, since that is the attribute value specified in the markup.

The link function in this example uses scope.$watch to listen for changes in the specified model value. $watch is a good topic for a future post, but for now we can say if the model changes it’s visible property from false to true, the framework invokes the listener function passed as the second parameter to $watch.

The listener function in this sample sets the display property of the element to an empty string or “none” to toggle visibility of the element. The value parameter in the function is the recently changed model value, the value the directive set up to $watch.

Where Are We?

This sample doesn’t show the full capabilities of a directive, which can also load additional markup from a string or a URL, as well as other nifty features.  We’ll cycle back to more advanced features in a future post.

Although custom directives can require  more code in a project compared to using DOM manipulation inside a controller, the advantage of having a directive in place is in keeping the models and controllers simple. Plus, once written, most directives can be parameterized and reused in different places and multiple applications.

Using elemMatch in a MongoDB Query

Monday, May 27, 2013 by K. Scott Allen

I introduced a latent bug in some code recently while trying to find documents with a specific set of values embedded inside an array. For example, consider the following documents:

{
    "name" : "Thing1",
    "children" : [  
        { "name" : "C1", "value" : "A" },
        { "name" : "C2", "value" : "B" },
        { "name" : "C3", "value" : "C" }]
}, {
    "name" : "Thing2",
    "children" : [
        { "name" : "C3", "value" : "A" },
        { "name" : "C4", "value" : "B" },
        { "name" : "C5", "value" : "C" }]
}, {
    "name": "Thing3",
    "children": [
        { "name": "C5", "value": "A" },
        { "name": "C6", "value": "B" },
        { "name": "C7", "value": "C" }]
}

Let’s say we only want documents with a child entry that has a name of C3 AND a value of C (only Thing1 should match this criteria because of the last child in its array). It’s tempting to write a query with an AND clause and feel good about the C# code.

var query = things.Find(
    Query.And(
        Query.EQ("children.name", "C3"),
        Query.EQ("children.value", "C")
    ));

But MongoDB, being document oriented, interprets the query as “give me all the documents that have any child with a name of C3, and any child with a value of C. In other words, the name and value combination don’t need to match inside the same array element. A quick test from the shell can verify the behavior.

> db.things.find({"children.name":"C3", "children.value":"C"},{name:1, _id:0})
{ "Name" : "Thing1" }
{ "Name" : "Thing2" }

The $elemMatch query operator tells Mongo to only match documents when at least one element in the array satisfies the entire criteria.

var query = things.Find(
    Query.ElemMatch("children",
        Query.And(
            Query.EQ("name", "C3"), 
            Query.EQ("value", "C")
        )
     ));

The shell will verify that we only get the Thing1 we want:

> db.things.find({ children: { $elemMatch : { name:"C3", value:"C"}}}, {name:1, _id:0})
{ "Name" : "Thing1" }

Not an easy bug to catch in a test without a robust set of test data.

AngularJS Abstractions: Filters

Monday, May 20, 2013 by K. Scott Allen

Filters in AngularJS can form a pipeline to format and adapt model data inside a view. The built-in filters for AngularJS are date (format a date), filter (select a subset of an array), currency (format a number using a currency symbol for the current locale), and many more. I say filters can form a pipeline because you place them inside expressions in a view using a pipe symbol. The canonical example of a filter is the filter filter, which in the following markup filters a list of items according to what the user types in the search input (try it live here).

<input type="search" placeholder="Filter" ng-model="searchTerm"/>    

<ul ng-repeat="item in items | filter:searchTerm | limitTo:maxItems">
    <li>{{item}}</li>
</ul>

Notice the output of filter is also piped to a limitTo filter, which restricts the number of items in the list to maxItems (where maxItems would need to be defined in the model).

Custom Filters

Custom filters only require a filter function to be registered with Angular. The filter function returns a function that will perform the actual work. For example, a plurify filter to add the letter s to the output:

(function() {

    var plurify = function() {
        return function(value) {
            return value + "s";
        };
    };

    angular.module("patientApp.Filters")
           .filter("plurify", plurify);
}());

Now plurify is available to use in a view:

<ul ng-repeat="item in items | filter:searchTerm | limitTo:maxItems">
    <li>{{item | plurify }}</li>
</ul>

A filter can also take one or more optional parameters.

var plurify = function() {
    return function(value, strength) {          
       strength = strength || 1;
       return value + Array(strength + 1).join("s");
    };
};

Now we can add 5 s characters to the output:

<li>{{item | plurify:5 }}</li>

The beauty of filters is how you can package up small pieces of testable code to make the job of the model and view a bit easier, and the syntax to use a filter is easy and intuitive.

Using system.js in MongoDB (From C#)

Friday, May 17, 2013 by K. Scott Allen

The official MongoDB docs recommend that you avoid storing scripts on the server, but there are scenarios where having reusable functions available on the server can be useful. Inside a MapReduce operation, for example.

We’ll start with some JavaScript code encapsulating statistical calculations, and place the code in a file named mathStats.js:

function() {

    var stdDev = function(numbers) {
        // ...  
    };

    var mode = function(numbers) {
        // ...
    };

    var mean = function(numbers) {
        // ...
    };

    return {
        stdDev: stdDev,
        mode: mode,
        mean: mean
    };

};

Note the script must be a function. To use the methods inside, the function must live in the system.js collection. The following C# code can do this:

var sysJs = db.GetCollection("system.js");
var code = File.ReadAllText("pathTo\\mathStats.js");
var codeDocument = new BsonDocument("value", new BsonJavaScript(code));
codeDocument.Add(new BsonElement("_id", "mathStats"));
sysJs.Insert(codeDocument);

It is important to insert the script as the  value attribute of a document, and set the _id of the document to a friendly string name and not an ObjectID value. Failing to follow those two steps can lead to errors like “exception: name has to be a string” and “value has to be set” when you execute commands.

Once the script is loaded, you can use the function from any map, reduce, or finalize function by invoking the function with its friendly _id name. For example:

function(key, value){                      
    var stats = mathStats();
    value.stdDev = stats.stdDev(value.items);               
    return value;
}

AngularJS Abstractions: Scope

Thursday, May 16, 2013 by K. Scott Allen

Continuing from the controllers post, the parameter to the controller function is named $scope.

var AboutController = function($scope) {

    // ...    

};

The name $scope is important since it allows the AngularJS dependency injector to know what type of object you are asking for, in this case an object that will contain the view model. Any plain old JavaScript you attach to $scope (properties, functions, objects, arrays) is eligible to use from the expressions inside the view.

In the last post our model was relatively “flat” in the sense that properties and functions were added directly to $scope:

$scope.rabbitCount = 2;

$scope.increase = function() {
    $scope.rabbitCount *= $scope.rabbitCount;
};

This allowed us to use rabbitCount and increase() in the markup that was inside the view scope (the div) of the AboutController:

<div data-ng-controller="AboutController">

    <div>Number of rabbits in the yard: {{rabbitCount}}</div>

    <button ng-click="increase()">More rabbits</button>
    
</div>

You can think of $scope as the execution context for the expressions in the view. Saying ng-click=”increase” results in a call to $scope.increase. The only thing tricky to understand about $scope is that having a controller inside a controller, or a controller inside an application (which you’ll always have), will result in nested $scopes, and a nested $scope will prototypally inherit from it’s parent scope by default. This is why $scope is injected by angularJS – the framework sets up the prototype chain before giving your controller the $scope object to use as a model.

Inheritance means a view has access to it’s own scope as well as any inherited scope. In the following example, the view inside the ChildController markup can use an expression like {{rabbitCount}}, and this expression will read the rabbitCount property of AboutController’s scope ($scope.rabbitCount will follow the prototype chain).

<div data-ng-controller="AboutController">    

    <div>Number of rabbits in the yard: {{rabbitCount}}</div>
    
    <div data-ng-controller="ChildController">
        Number of rabbits in the yard: {{rabbitCount}}
        Number of squirrels in the yard: {{squirrelCount}}
    </div>

</div>

The one place to be careful with the inherited scope is with 2 way data binding. The way JavaScript prototypes work is that writing to the rabbitCount property of the ChildController $scope will add a rabbitCount property to the ChildController $scope and effectively hide the parent property. $scope.rabbitCount no longer needs to follow the prototype chain to find a value. More details and pictures on this scenario in “The Nuances of Scope Prototypal Inheritance”.

Where Is .NET Headed?

Wednesday, May 15, 2013 by K. Scott Allen

I watched the dotNetConf .NET Open Source Panel last week. It was a bit disappointing to hear defeatism in the voices of OSS project leaders, because .NET’s future appears to rely entirely on the success of open source software for .NET. Here are a couple reasons:

1. The success of Windows Azure. Azure is now an amazing cloud platform for developers and is getting better every few weeks. Azure is also a business success with annual revenue topping $1 billion. That’s $1 billion with only a 20% share of a $6 billion dollar market – a market that is expected to grow to $30 billion in 4 years. As Azure continues to pick up market share it is not completely unthinkable to see it post a 15+ billion dollar year in 2018, which is getting into the same double-digit-billion-dollar-revenue neighborhood as Windows itself.

The documentation page for Azure makes it clear where the growth will come from:

Azure Strategy 

To paraphrase the above graphic, Microsoft doesn’t need legions of developers building frameworks and tools for Windows developers when they can have legions of programmers building tools and a cloud platform for all developers. Hadoop, Redis, NodeJS, RoR, Django, PHP, and the list goes on. Even if it doesn’t run on Windows, you can always spin up a ready made Azure virtual machine image with Ubuntu, CentOS, or SUSE.

I don’t think Azure needs a successful server-side .NET framework to be a success itself.

2. The Direction of Windows 8.

I still feel Window 8 carpet bombed .NET developers. There was secrecy and hearsay followed by the death of one XAML platform and the arrival of yet another slightly different XAML platform. People running a business based on desktop technology don’t know where to place their bets and the Windows division has always appeared hostile to the CLR. I’m not sure what this year’s Build and Windows Blue will bring, but I can only hope it offers some direction for businesses who build desktop business applications with managed code.

I don’t think Windows wants to see a successful client-side .NET framework.

Where Are We?

It feels as if Microsoft has shifted focus away from .NET, and with the focus goes resources and innovation. Much of the CLR and it’s associated assemblies and languages appear to be entering maintenance or refinement mode instead of advancing in new directions. Anyone building software on Microsoft’s .NET platform should see this as cause for concern.

Except …

The circle of  software loosely surrounding .NET is exploding. There are more server side framework choices for C# developers than ever before, and client side web programming has advanced rapidly over the last few years with open source projects like AngularJS, Backbone, Ember, and Meteor. Document databases like MongoDB and RavenDB and key-value stores like Redis are all available to managed code, and products like Xamarin are pushing C# and mono to new platforms. What I’ve listed is a small sampling of what is happening and it is all pretty amazing when you sit back and look at the bigger picture. 

Plus, if you already build solutions with ASP.NET MVC, Web Pages, the WebAPI, or the Entity Framework, you are already building software on top of open source projects that rely on other open source projects from the community. 

What To Do?

If your business or company still relies solely on components delivered to developers through an MSDN subscription, then it is past time to start looking beyond what Microsoft offers for .NET development so you won’t be left behind in 5 years. Embrace and support open source.

At least, that’s how I see things.