Dependency Injection with AngularJS – by Alex Knol

Dependency Injection with AngularJS – by Alex Knol
Disclaimer – I have been contacted by Packt publishing to read and comment the book. Except the book itself I did not get any benefits or compensation.
Dependency Injection with AngularJS – by Alex Knol
Dependency Injection with AngularJS – by Alex Knol

With this book about AngularJS Dependency Injection, Alex Knol attempts to focus on one but surely the most important part of AngularJS components.

You’ll first find a brief introduction about AngularJS, how to setup, and samples to get started. The book will then guide you through good practices and to the why and the how dependency injection helps your application to scale with new features. It covers the SOLID principles, and the complex subject of unit and functional (or e2e) testing with many code samples. Also it suggests code architecture to avoid your application to become a giant mess of .js files.

About the book itself, while it remain a very good introduction to enterprise level application with AngularJS, it stills focus on the essential of the dependency injection component of AngularJS. Experts won’t find here a complete description of all the facets of the library (factories, providers, container hooks and building process…). On the other hand, beginners and intermediate programmers will have a good vision of the power of dependency injection done right with AngularJS.

You can find the book on Pack here and follow Alex here.

An AngularJS CRUD using Azure Mobile Services

Lately, we saw very promising web technologies coming out. I am currently exploring some new web applications stacks that are more RAD and flexible. I especially focused on angularJS and Azure Mobile Services which are in my opinion two of the most interesting technologies of the past months.

Why AngularJs?

AngularJSI would describe AngularJS as a javascript view oriented framework. It offers a very element way to build dynamic web pages using two-way binding, events, controllers, router, … I particularly the very elegant and direct approach of solving the issue by keeping very close with the javascript philosophy. It is comparable to KnockoutJs, EmberJs, or BackboneJs, but I choose none of those because I found they over-thought the issues with too much code and abstractions.

Why Azure Mobile Services?

Windows AzureAt first Azure Mobile Service sounds like a plateform for mobile applications. It offers an online SQL storage with SDKs for iPhone, Android and Windows Phone plateforms for easy CRUD access. It also has some bonuses like a push notification system and a dynamic mode where the SQL schema is enriched every time a new field is pushed on a table. What’s more is the fact that the online stack is an SQL database with a nodejs frontend acting as a REST service. There is also now a javascript SDK that allows web-applications to connect with the storage service.

Building a CRUD

My tutorial is about creating a CRUD for Azure Mobile Services using AngularJS, an interesting alternative has been brought recently using AmberJS, but, as I said, I prefer AngularJS.

First, setup mobile services:

1. First of all you need an Azure account with the preview for Mobile Services activated.
2. Create a mobile services:
Create an Azure Mobile Services
3. Follow the wizard steps then go to your newly created service.
4. Then go the the Data tab then create a table:
Create a data table
5. In the configure tab, be sure that the dynamic schema is activated and that your development/production host is in the cors configuration:
Configure the service
6. In the dashboard tab, note the mobile service url, and in the manage keys popup, get your Application Key:
Get you service url and application key

Then, lets prepare our angular website:

1. The first thing to do is to create a js file, configuring a resource to your mobile service table:

// mobile-service.js
'use strict';

angular.module('mobileServices', ['ngResource']). // new service mobileServices depending on ngResource
    factory('Task', function($resource) { // declaring a MyTable resource
        return $resource('https://myservice.azure-mobile.net/tables/task/:taskId', {taskId: '@id'}, // binding to the table url
            {
                'update': { method:'PATCH' } // adding an update function
            }
        );
    });

Here a new service named mobileServices is configuring the ngResource service to provide a Task resource connected to the table named task in our Azure Mobile Service. Note that we added a supplementary update action that uses the method PATCH. This is because Azure mobile service uses POST only for creation and PATCH must be used for update. Note that the Task resource is already provided with get, query, save, remove and delete.

2. In the app.js file configuring angularjs, lets tweak some code:

// app.js

angular.module('myapp', ['mobileServices']). // setting up our app to use the mobileServices service
    config(['$httpProvider', function($httpProvider) { // coniguring the httpProvider
        $httpProvider.defaults.headers.common['X-ZUMO-APPLICATION'] = 'myapplicationkey'; // add the application key
        $httpProvider.defaults.headers.common['Content-Type'] = 'Application/json';
    }]);

We just configured our app to use the mobileServices service and added the application key that will allow authentication to he Azure Mobile Service.

3. Now, you can easily import the Task resource in any controller, here is an example:

// controller.js

function MyCtrl($scope, Task) {
    $scope.tasks = Task.query(); // load all tasks
    $scope.newTask = new Task(); // create an empty new task

    // saving a new task
    $scope.createTask = function() {
        // call the service
        $scope.newTask.$save(function() {
            // when saved, reload the list and recreate a new task
            $scope.tasks = Task.query();
            $scope.newTask = new Task();
        });
    }

    // removing a task
    $scope.deleteTask = function(task) {
        // call the service
        task.$delete(function() {
            // when deleted, reload the list
            $scope.tasks = Task.query();
        });
    }

    // saving an existing task
    $scope.updateTask = function(task) {
        // call the service
        task.$update();
    }
}

Ad you can see, this commented controller is very straight forward. The controller has a list of tasks and an empty one dedicated to the creation process. Three functions allows to create, update and remove a task.

4. To complete the example here is a possible HTML usage:

<!DOCTYPE html>
<html ng-app="myapp">
<head>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript" src="angular.js"></script>
    <script type="text/javascript" src="angular-resources.js"></script>
    <script type="text/javascript" src="mobile-service.js"></script>
    <script type="text/javascript" src="controllers.js"></script>
    <script type="text/javascript" src="app.js"></script>
</head>
<body>
    <div ng-controller="MyCtrl">
        <ul>
            <li ng-repeat="task in tasks">
                <input type="checkbox" ng-model="task.done"
                       ng-click="updateTask(task)">
                <span>{{ task.text }}</span>
                <a ng-click="deleteTask(task)">delete</a>
            </li>
        </ul>
        <form ng-submit="createTask()">
            <input type="text" ng-model="newTask.text"
                   placeholder="add new task here">
            <input type="submit" value="create">
        </form>
    </div>
</body>
</html>

Here we display the list of task. Each item has a checkbox which is instantly saved upon click and a delete button. Also a form allows the creation of a new task.

Wrap up

Thanks to AngularJS + Azure Mobile Services. In a very few lines of codes and configuration, we were able to build a CRUD web application in a very reactive way.

Extended customization of jQuery UI Autocomplete

Extended customization of jQuery UI Autocomplete

I recently, spend quite a few time looking into a brand new jQuery UI widget for extensibility point in order to get a real customization.

As usual, the widget comes with a various panel of options and events, but I really wanted uncommon behaviors.

Use case

On my new website I can associate tags to my business object. I already implemented an indexer in order to retrieve tags from a simple AJAX query, I just want to add a fancy UI. Thus I added a simple text input to my form on which I want to bind my indexer via jQuery UI Autocomplete.

Here is my html:

[html]
<input type="text" id="tag-input">
<div id="tag-list">
<span>Microsoft<input type="hidden" value="1" name="object[tags_list][]"></span>
</div>
[/html]

You can see here that I placed a text input that I will “jQueryUIze” and a div that will hold my selected tags. I already put one tag into it so that you can see exactly what DOM structure I need to correctly post my form. The tag is represented using a hidden input and the held value is the Id of my tag.

A simple first implementation of the jQuery widget could be:

[js]
$("#tag-input").autocomplete({
minLength: 3,
source: function(request, response) {
$.ajax({
url: "/tag/suggestion.json",
dataType: "json",
data: { query: request.term }
});
}
});
[/js]

Here I just implemented some built-in features of the widget. When I type more than 3 characters, an AJAX request is made to my server. For example, when I type “Micro” this url is requested: /tag/suggestion.json?query=micro.

Now let’s override it !

Apply a specific data mapping

First, you need to remember that I want to share more than a simple label because I need the Id in order to correctly add it into my tag list. Also, I would like to have the requester term set to bold into my suggestion list.

Thus, here is the returned json:

[js]
{"tags":[
{
"id":"1",
"label":"Microsoft"
}
]}
[/js]

In order to correctly use the json data I need to add two modifications. First I am going to map the ajax result and then edit the renderer of the widget:

[js]
$("#tag-input").autocomplete({

//…

$.ajax({
url: "/tag/suggestion.json",
dataType: "json",
data: { query: request.term },
// 1rst need a specific mapping from my json data
success: function( data ) {
response($.map(data.tags, function(item) {
//this regex is for the bold of the suggestion list
var label = item.label.toString().replace(new RegExp(‘(‘+request.term+’)’,’i’),'<strong>$1</strong>’);
return {
// for each tag, I will retrieve a object with these 3 properties
id: item.id,
label: label,
name: item.label
}
}))
}
});

//…

//this 2nd modification is for the rendering of the suggestion list
}).data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( ‘<a href="#"><span class="tag">’ + item.label + "</span></a>" )
.appendTo( ul );
};
[/js]

You can already notice the two modifications. The first one is to translate every tag from my json into an object composed of three properties: the id for the form submission, the label for the suggestion list and the name for the form display.

The second modification overrides the item renderer. For each item it need to render, it simply creates a list item (li) on witch I add the item (we will use it later), append the proper layout (a link with a span and the label), and then add it to the suggestion list (ul).

Now I have the rendering that I expected!

After customization

Customize behaviors

Now, I want that when I select an item it flushes my search and append the selected tag to my tag list. In order to pass through this issue I will simply use the select event of the Autocomplete widget:

[js]
// when a element of the suggestion list is selected
select: function(event, ui) {
var canAppend = true;
//crawl the current tags to see if I can append it or not
$(‘#sticker-list .sticker input’).each(function(){
if($(this).val() == ui.item.id)
canAppend = false;
});
//add the tag to the tag list
if(canAppend)
$(‘#tag-list’).append(‘<span class="tag">’+ui.item.name+'<input type="hidden" name="object[tags_list][]" value="’+ui.item.id+’"></span>’);
//clean the value of the input
$(this).val("");
//return false to prevent update of the input
return false;
}
[/js]

The select event is called every time a item from the suggestion list is selected. When it occurs, I simply need to know that ui.item contains the item that constructed via the costom mapping (1rst modification) and passed trough the custom rendering to my DOM element (2nd modificcation). Now, I can check if the tag is not already in my tag list and append it.
The last thing to do is to empty the text input and prevent the default behaviour that will fill the input with the selected item. In order to do that I just nedd not to forget to return false.

And voila! We made a complete customization of the jQuery UI Autocomplete widget.

You can download the full example here : Autocomplete Customization.