Angular Workflow with Node, Yeoman, Grunt and Bower.

  1. Introduction
    1. Why such Workflow
    2. Classical Web Development
  2. Hands-On Tutorial
    1. Grunt
    2. Node
    3. Yeoman
    4. Installing Node.js
    5. Installing Yeoman, Grunt, Bower
    6. Use Yeoman the first time
    7. Starting Grunt
  3. Developing with Angular
    1. Hands-on Dependency Injection
    2. Setting up routes in a Module
    3. Creating a new Controller
  4. Accessing APIs
    1. Binding the data model to the local scope
    2. Accessing the Model from the View
    3. Binding model data to the view
    4. Automatic view routing with dynamic models
  5. Angular Filters
    1. Sorting
    2. Searching
    3. Even more build-in filters
    4. Custom Filters
  6. Deployment with Grunt
  7. Conclusion
  8. References

Introduction

Why such Workflow?

Imagine installing a full-stack development infrastructure with Unit Tests, Linting, Package Management, IDE, Versioning, Software Updates, Security Fixes and much more in under 30 Minutes including a ready-made fully responsive application.

Sounds to good to be true?

By using Package management provided by Node, Yeoman and Bower and by using the power of Grunt to watch your project files adn do automatic unit testing you are indeed able to do just that. Usually such undertaking would need hours, to be honest, days of setup if done with classic development tools like Apache, Tomcat, Wildfly, Eclipse or others. While approaching software development with an application stack like LAMP or Java/JSP may have its benefits with certain requirements, it is arguably slower to get going or to write and code.

I promise you if you are confident with developing with open source software you will be able to have this API-wired Single Page App done in under an hour, including setting a Development stack that scales.

Classical Web Development

1990s: Java and PHP

In classical web development which has started in the early 1990ies we are using PHP, JSP or Ruby on Rails to alter the data model before it is sent to the client or browser.

classical-software-stack

2000s: JQuery

JQuery does extend this model to the browser and enables us to reload parts of the model seperately into the Document Object Model without a page refresh, however there will be HTTP GET Requests to the server where the model resides. With JQuery you have to predefine place holder HTML elements in your view to fill them with concatenated strings fetched from the server.

If you want to alter the data model in both directions from the user and to the user, you will have to code repeatedly the same routines, in order to keep the data model consistently in the correct form. This is where Angular.js or Ember.js comes in.

2010s: Angular.js, Ember.js

Angular is mapping parts of the UI (HTML) to JavaScript properties (Controller) and is synching both parts automatically. This is called Bi-Directional Data Binding and it is one of the many features what makes Angular.js a killer JavaScript Framework. It is not yet another JS library - which it should not be mistaken for.

Data binding

Data Binding works great in tandem with MVC in order to reduce code when you are implementing the view and the model. With Angular the Model can on the view (HTML), which is why Angular's software architectural pattern is often called Model View View Model - MVVM.

mvvm

Other great architectural features of Angular are client site templates, dependency injection, directives, filters, services, routing and other architectural patterns that force you to design a app that can scale. It can scale as much as Google's Doubleclick for Publishers which is entirely written with Angular.js. DFP is by far the biggest eCommerce application on the Internet.

I also mentioned Ember.js, because it tries to take the Angular way of application design to another level. You can familiarise yourself with the benefits of Ember.js vs Angular in this article or in this one.

Hands-on Tutorial

This Step-By-Step Tutorial was tested on Linux and MacOSX, however it should work with Windows. You will need to alter certain path variables in Windows and make yourself acquainted with the console, be it the one from Ms Sys Git or the Powershell.

The Tutorial will let you take a first dip into the realm of Angular, Node, Grunt and Yeoman. I will explain what these tools are and why there are an important part of integrating Angular into your Software Development work flow.

Grunt

Grunt will be your Web Server, Test Framework, Linting tool and essentially code quality watchdog. The Grunt Dev team itself says about Grunt:

The less work you have to do when performing repetitive tasks like minification, compilation, unit testing, linting, etc, the easier your job becomes.

Node

Node is a highly efficient Web server based on Google Chrome's JavaScript V8 engine, which is now the most used Desktop Browser world wide.

Node.js is said to be faster than any other Web server on the planet and makes it perfect for small and huge network applications alike. The node team says about node:

Node.js is a platform for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.

Yeoman

Yeoman is a tool that lets you generate ready-made structured projects with pre-written template code for repetitive tasks such as server-communication, authentication, controllers, templates and much more. Again we use the words of the developer team to describe this great open-source product:

Through our official Generators, we promote the "Yeoman workflow". This workflow is a robust and opinionated client-side stack, comprising tools and frameworks that can help developers quickly build beautiful web applications. With a modular architecture that can scale out of the box, we leverage the success and lessons learned from several open-source communities to ensure the stack developers use is as intelligent as possible.

Installing Node.js

Windows

Running node in Windows is like getting a quantum mechanical warp drive run on a Fixie Bicycle

  • Download and install the git shell https://msysgit.github.io Install it with the full bash tools feature (the red warning one)
  • Download node.exe from the node Website (not the MSI installer)

Open Git Bash:

mkdir /c/node
mv /c/Users/You/Downloads/node.exe /c/node/
vi ~/.gitconfig

Put this into .gitconfig:

[url "https://"]
        insteadOf = git://

Open cmd.exe:

set path=%PATH%;%CD%
setx path "%PATH%"

Back in Git Bash, you need to create an ssh key for git to use. If you don't know how, follow this Tutorial.

Touch and edit ~/.npmrc:

proxy=http://proxy:port/
https-proxy=http://proxy:port/

Alternatively, include your Active Directory Domain:

proxy = http://AD_Domain\\proxy:8080

Then, although this is not related to node, touch and edit ~/.bowerrc:

{
  "proxy":"http://proxy:8080 <http://proxy:8080/> ",
  "https-proxy":"http://proxy:8080 <http://proxy:8080/> "
}

Other open source community instructions.

Mac

Install Brew to inject a proper open-source package manager inside Apple's binary operating system. To do this, do a:

$ brew install node 

Linux

$ sudo apt-get install node 

Installing Yeoman, Grunt and Bower

Now that you have a development environment setup on any of the major operating systems, we can start installing Yeoman, Grunt and Bower.

Bower? This is what the Development Team of Bower has to say about their package manager system:

Bower works by fetching and installing packages from all over, taking care of hunting, finding, downloading, and saving the stuff you’re looking for. Bower keeps track of these packages in a manifest file, bower.json

Let's install it all in one go:

$ npm install --global yo bower grunt-cli 

Time to install our first Generator, in our case the generator-angular, which is far from being the best generator out there - e.g. generator-angular-fullstack is much better - yet it is simple enough for getting started and show basic capabilities of Angular.js.

$ npm install --global generator-angular 

Use Yeoman the first time

$ yo 

In the Wizard leave the defaults, except for SASS, there we select static CSS (StyleSheets) in order to get going quickly.

yeoman-wizard

Now let's install all dependencies in the bower.json file provided by yeoman:

$ bower install 

Since we have chosen to use classical cascading stylesheets, we need to install bootstrap, which will give us a beautiful CSS framework ready-to-use.

$ bower install bootstrap 

Starting Grunt

$ grunt serve 

Grunt now runs the lintin and (very) basic testing of your code and then acts as development server, while watching your project directory structure for any file changes, upon it will restart the linting and serving process.

Grunt Screenshot

A browser window will now open and our app should be displayed.

Yeoman Angular Generator in the Browser Screenshot

Developing with Angular

If you click around on the application, you will notice immediately that a few things do not work, e.g clicking on the navigation (routing), does not work properly.

Hands-on Dependency Injection

Injecting ui-router

Since the default routing mechanism by angular is not the best out there, and stuff does not seem to work our-of-the box with our yeoman angular generator, we need to inject our first module, ui-router. First, we install it with bower:

$ bower install ui-router 

Then we insert ui-router in our index.html like this:

<script src="bower_components/ui-router/release/angular-ui-router.js"></script>

Your app and folder structure should look like this now:

Now that we have opened index.html already, let's set-up the routing with ui-router as well:

<li><a ui-sref="home">Home</a></li> 
<li><a ui-sref="adressbook">Adressbook</a></li> 
<li><a ui-sref="contact">Contact</a></li> 

Don't forget to implement the part where all the templates will get injected into our single page app:

<div ui-view></div> 
Finally we inject the module in our main app.js like this: angular .module('hackathonAngApp', [ 'ngAnimate', 'ngCookies', 'ngResource', 'ngRoute', 'ngSanitize', 'ngTouch', 'ui.router' ]) ## Setting up routes in a Module Now that we have injected ui-router into our application (the main module) and in the controller of adressbook.html, we want to configure the page routing itself. So, make sure your app.js looks like this: ## Creating a new Controller Make sure you have a **addressbook.js** in your `scripts/controller` folder. You could choose any other name, of course. Then navigate to that file and open it. Make sure you attach the controller to your main app module, in our case we named it `hackathonAngApp`: angular.module('hackathonAngApp') .controller('AdressbookCtrl', function ($scope, $http) { As you can see, there are several different things happening here. We are attaching Angular's controller method to our main module and passing into it a anonymous function which itself is getting injected with the dependencies we will need in a minute, namely the `$scope and `$http` modules. ### Linking against the controller Before we continue make sure, we linked our adressbook.js in the index.html file like so: # Accessing APIs In our Adressbook.js Controller we now want to actually do useful stuff and access a data model. We use the excellent http://filltext.com API, which is optimal for testing out code. We use the `$http` module to access its `jsonp` method (there are other ways of doing this) and fetch data from the FillText API. This is how our code will look like after implementing this: ## Binding the data model to the local scope Now let's do something with that data from the data model we just fetched. Let's implement the `.success` promise and attach it to the $http.jsonp method. The ``success(callback)`` data structure expects us to pass in a callback function. We do so and hand it over the data fetched by the HTTP Request. `data` is the Raw JSON data, and since this is still pure JavaScript, we can just utilise it and bind it to a variable. In our case the variable is `$scope.people`, an Object bound to the local scope of AdressbookCtrl. In our app.js we defined adressbook.html to lie in our local scope, so the scope variables will be accessible directly there, in HTML. This is how our controller code should look like by now: ## Accessing the Model from the View Now let's wire everything up in our view, the adressbook.html like so: Headings: id first last city Iterating through the people model: {{person.id}} {{person.fname}} {{person.lname}} {{person.city}} What this actually looks like in the Browser is shown in the following screenshot - however at the moment without the links - which we will add in a later step. angular generator extended screenshot ### Sublime and Emmet In case you want to write above code by hand, there is a better way. Do a $ apt-get install sublime to install Sublime, now get [Package Control]( https://sublime.wbond.net/), place it into your sublime installed packages folder, usually residing in your user folder like so: `.config/sublime-text-2/Installed Packages/Packe Ctonrol.sublime-package` Now inside Sublime, do a *cmd-shift-p* (on Windows and Linux: *ctrl-shift-p*) and type `Package Control: Emmet` and install it. Now you can write above html like so `table>thead>td*4` `table>tr>td*4` `table.table-striped>tr>td*4` ..by pressing simply *tab tab* after each line. Imagine all those hours saved in your workflow if you would have had this 20 years ago. ## Binding model data to the view What else is happening in the adressbook controller snippet? We are also injecting ui-routers `$stateParams` method. So this line $scope.person=$scope.people[$stateParams.id]; gets invoked when a `href` or `ui-sref` passes in some parameter. In above case you can maybe already see that we are preparing for fetching a single person's id (inside people data) and attach it to our local scope with the variable name `$scope.person`. For this to work, let's utilise ui-router in our addressbook.html like this: Now if somebody clicks on a person in the people model, the unique id of that person will get passed into ui-router. ## Automatic view routing with dynamic models To make dynamic routing happen, let's enhance our router like this: As you can see the router will now forward to nested sites inside the **view route** named dynamically after the id of a person. Now all that is left to do is to create the view.html. Please note for this to work, you have to wire view.html to the addressbook.js Controller like in above Gist. This is the view.html I would propose to use. If you followed carefully, the *view.html*, when clickling on a person in the addressbook, should look like this in the Browser: ![angular generator view.html in the browser](http://res.cloudinary.com/meshfields/image/upload/v1418343649/Bildschirmfoto_vom_2014-12-12_01_11_26_hjyxpw.png) The complete code should look like this Plunkr. Please Note that I had to flatten the directory structure in order to make it work inside of Plunker: http://embed.plnkr.co/bS200tmBNDDRtxfNztvy/ # Angular Filters Now a few snippets of code that you can easily plug into your app in order to filter or search the data directly in the view: ## Sorting And negative sorting: orderBy: '-fname' Sort by multiple criteria: ['fname','lname'] ## Searching Search our data mode directly from the view: and input this into the **ng-repeat directive**: filter:search Search only for a particular field in the JSON data: ## Even more build-in filters {{person.id | currency}} {{person.fname | uppercase}} {{person.lname | lowercase}} ## Custom Filters Let's write a filter that gives us back the initials of the name and familiy name of each person in our data. **HTML** {{person.fname + ' ' + person.lname}} {{person.fname + ' ' + person.lname | initials}} **Controller** .filter('initials', function(){ return function(text) { var names = text.split(' ') var holder = []; angular.forEach(names, function(item){ holder.push(item.substring(0,1) + '.') }); return holder.join(''); } }); # Deployment with Grunt * http://code.tutsplus.com/tutorials/building-apps-with-the-yeoman-workflow--net-33254 * http://tylerhenkel.com/creating-apps-with-angular-and-node-using-yeoman/ # Conclusion

As we could see, Angular makes accessing, filtering, searching and altering (not in this tutorial) data really easy, and possible directly in the view of your app. As you could also hopefully see, we did construct a powerful Web app in no time, without wasting much thought about:

  • Reloading the Browser or Linting the Code after each File-Save
  • UI/UX and Stylesheets
  • Browser Incompatibilities
  • How to get data from the database
  • How to get data from the server to our controller and parse it for our view
  • Constructing a Navigation with correct States in the browser address bar and a working browser return button functionality
  • Responsiveness, Mobile First

All the above was done by Angular for us. Coding feels like coding HTML in the 1990s again, but we now have a written an extensive, scalable Application with API access and many views. In addition, Grunt will enable us to run extensive Unit Tests over our code after each file-saving. But this I will leave for another time. Thanks for reading.

References

Angular.js Documentation
https://docs.angularjs.org

Sublime & Package Control
https://sublime.wbond.net/installation

Emmet
https://sublime.wbond.net/packages/Emmet

JS Refactor
https://sublime.wbond.net/packages/JavaScript%20Refactor