YAAP: Yet another AngularJS Presentation – The changing web – Why AngularJS?



YAAP: Yet another AngularJS Presentation – The changing web – Why AngularJS?

1 4


AngularPresentation

Yet Another Angular Presentation

On Github cjus / AngularPresentation

YAAP: Yet another AngularJS Presentation

Presented by Carlos Justiniano / @cjus / Presentation version: 0.5

A few words about this presentation

  • We won't cover all of Angular - it's too big silly!
  • This is built using Reveal.js, featuring AngularJS
  • It's mobile and tablet friendly for your viewing pleasure
  • Entire project available on Github
  • The source code featured is stored within the project
  • Issues with this presentation? Fix it and issue a pull request
Latest presentation at: http://github.com/cjus/AngularPresentation

This presentation doesn't all of Angular. In fact, many parts were intentionaly omitted for brevity.

This is an interactive presentation, built on top of Reveal.js and featuring AngularJS.

This presentation is built entirely on HTML, CSS and JavaScript to run inside of your web browser.

The presentation is mobile and tablet friendly and the entire presentation is available on Github at the link shown on this page

All of the sample code featured is available in the samplecode folder within the project

If you find any issue with this presentation drop me an email or better yet, issue a pull request

The changing web

  • The advent of AJAX marked a web shift
  • As a result sites became more responsive
  • And increasingly complex web applications were being built

Before AJAX platforms like PHP, Python/Django and Ruby/Rails were used to help render web front-ends

That worked great but required pages to be refreshed to see any data updates.

By eliminating the need for full-page refreshes, AJAX marked an important shift in the development of the web.

Web applications became more responsive and increasingly more ambitious applications were being built.

Front-ends started relying less on backend servers as more application logic moved into the front-end.

This benefitted the backend because rendering, logic and computation could be distributed to user machines allowing backends to more easily scale.

Handling front-end complexity

  • Code moves into the front-end
  • Developers face increased code complexity
  • Enter: open-source front-end web frameworks with names like: Backbone, Ember, Knockout and Angular

As code moved into the front-end and front-ends became richer, developers found they needed ways to handle the increased front-end code. They were forced to consider how large applications are built using software libraries and frameworks and bring some of that native and server goodness to front-end development.

They begin developing open-source front-end web frameworks with names like: Backbone, Ember, Knockout and Angular.

Today there are no lack of choices regarding framework. However, Angular has made a name for itself and many of the developers I meet are genuinely excited about it.

AngualrJS

  • Angular is loosely similar to many of the other frameworks that emerged to address the increasing demands of modern web development
  • However, the similarities quickly give way to an amazing array of cleanly integrated and forward thinking features
  • We'll cover many of Angular's features in this presentation

Frameworks like Backbone, Ember and Knockout are great for building single page web applications.

However, as an application grows older frameworks require developers to do more work to keep their applications maintanable.

Why AngularJS?

  • Embraces the spirit and potential of HTML5
  • Offers features which are designed to work together
  • Simplifies building modern web application
  • When used correctly, it makes your code highly testable

Angular stands apart from other frameworks in that it is first and foremost about unlocking the potential of HTML.

Angular embraces HTML and extends it in ways which feel natural and uncontrived.

In fact, starting Angular developers eventually realize that if HTML and the DOM were more evolved then there wouldn't be a need for AngularJS.

Or AngularJS would be a lot different from what it is today. Perhaps, yet another MVC framework.

The original vision

Originally, Angular was designed as a way of enabling designers to use HTML markup to build application without having to know how to program

The originally goal for Angular was to provide a way for designers to use HTML markup to build application without having to know how to program

The core belief is that the best way to build user interfaces is by using declarative programming

In this approach, designers would be able to declare the behavior or components without knowing how the underlying behaviors were implemented

The basic premise is a powerful one: Allow designers to sketch using HTML, then allow developers to build components and behaviors.

Rinse and repeat

The more components and behaviors that developers build the more powerfully, designers can sketch and iterate.

What can Angular do for you?

  • Make it easier for you to reason about and build your web application - regardless of its size and complexity
  • Applications which embrace Angular's features are inherently more testable

Demo code

Here's the structure of the basic angular enabled page we'll reuse in this presentation.

  <!DOCTYPE html>
  <html ng-app>
  <head>
    <title>Basic Angular App</title>
  </head>
  <body>
    <script src="angular.min.js"></script>
    <script src="app.js"></script>
  </body>
  </html>
    

Before we dig too deeply into code lets examine a few core concepts...

Here is a basic HTML file that uses angular. We'll use this structure through this presentation. At the top of the file we see an ng-app attribute. This is simply a data tag which tells which part of the DOM to manage.

Within the bottom of the body tag we see that angular is loaded along with our app.js script.

This is all that is required to begin using AngularJS.

Before we dig too deeply into code lets examine a few core concepts and key features.

I promise we'll be back in code shortly.

Core Concepts and Features

The goal here is to get a sense of what's available and how we can take advantage of Angular in our own applications.

Embracing best practices

  • Angular borrows heavily from other successful frameworks
  • Angular implements popular idioms while embracing HTML and other web standards
  • It's more about embracing HTML than wrestling with it

Angular core developers would be the first to admit that Angular is based heavily on ideas which are far from new.

After all, developers were using existing JavaScript frameworks long before Angular was introduced.

What makes Angular interesting to developers is that it represents an evolution over older frameworks.

One that embraces web standards and modern best practices.

It's all about the markup

It's all about the markup. Well not actually.

However, Angular treats HTML as a first class citizen rather than an ugly girlfriend.

This focus on HTML is not misplaced as making HTML more useful and ultimately a pleasure to work is an important achievement

Angular makes this possible by embracing declarative programming

Declarative programming

Angular embraces HTML, by allowing designers and developers to describe what their HTML should do

We touched on this idea earlier, where Angular was designed to enable designers to "declare" the behaviors associated with their markup.

This declarative approach is different from the imperative approach we developers do when we write Python, Ruby or JavaScript code.

With declarative programs we describe what programs should do and not how they're implemented.

Angular embraces this approach allowing us to do this using directives and HTML behavioral annotations

A core Angular philosophy is that the best way to build UI's is using declarative syntax. With Angular we add behavior to HTML markup using directives.

Let's take a closer look at this directive stuff.

HTML5: increasingly declarative

HTML5 adds lots of new elements to HTML:

This helps relieve the pressure of overloading div elements in ways that makes HTML less readable.

The new HTML elements are great. But what if you wanted to create your own elements?

Angular, extends HTML to allow you do just that.

HTML5 data attribute

The HTML5 data attribute allows designers to specify additional properties and behaviors for HTML5 elements.

By querying the DOM, programmers can detect the presence of attributes to augment the element.

Coupled with the new HTML5 elements, data attributes contributed to providing considerably more expressive power than was previously available.

This was a really big step forward for HTML

HTML5 data attributes allowed frameworks like jQueryMobile to simplify building mobile applications.

In this example, jQueryMobile uses the data-role and data-filter-placeholder attributes to determine how the list should be transformed

  <ul data-role="listview" data-filter="true"
         data-filter-placeholder="Search fruits..."
         data-inset="true">
    <li><a href="#">Apple</a></li>
    <li><a href="#">Banana</a></li>
    <li><a href="#">Cherry</a></li>
    <li><a href="#">Cranberry</a></li>
    <li><a href="#">Grape</a></li>
    <li><a href="#">Orange</a></li>
  </ul>
    

From the above to this...

To this:

Beyond the mobile styling of what started off as simple markup, jQueryMobile has added behavior to mimic a popular component that allows for data navigation on mobile devices.

The rows highlight as the user moves up and down the list, and the button on the right cause the panel to side to the left revealing a detail panel.

The search field at the top of the control allows for filtering of the list in realtime.

Angular fully embraces this paradigm by allowing developers to build their own component using directives.

Angular calls these directives

Earlier, we saw examples of directives when we looked at HTML for our basic angular app

  <!DOCTYPE html>
  <html ng-app>
  <head>
    <title>Basic Angular App</title>
  </head>
  <body>
    <script src="angular.min.js"></script>
    <script src="app.js"></script>
  </body>
  </html>
    

The ng-app in the markup is an Angular directives used to inform Angular where the Angular application begins

Source: /samplecode/BasicAngularApp

When the Angular script loads it scans the DOM looking for the ng-app directive. Angular then restricts its operations to just the scope of the ng-app directive.

You can decorate a single div with the ng-app directive and only use Angular features within that div.

You can even create your own directives. We'll revisit this topic a bit later.

Extending HTML

The declarative nature of HTML and the ability to extend it using directives is fundamental to what Angular tries to help designers and developers achieve

Many of Angular's features are designed first and foremost to support this goal and secondarily to provide the tools required to build non-trivial web applications.

One way in which Angular does this is with a concept called data binding.

Other important features include

  • Data Binding: Bidirectional sync between model and views
  • Scope: A shared context used to store data, models
  • Modules: A container for organizing your code
  • Controllers: The C in MVC, business logic behind views
  • Dependency Injection: Just in time access to code
  • Providers: Factories and Service which are dependency injectable
  • Support for testing: Both BDD unit tests and End-to-End
  • And more...

Angular's ability to extend HTML using a declarative approach is what distinguishes Angular from other JavaScript frameworks.

And if that's all Angular offered it would still be a very useful tool.

However, Angular doesn't stop there. In fact, it goes far beyond that with a suite of tools to address building modern, complex and production ready applications.

Data Binding: This is angular's secret sauce for seamlessly syncing data between models and views.

Scope: The Scope in Angular is a shared context used to store model data. The cool thing about the scope is that it can be shared. Furthermore, expressions in views can access scope data.

Modules are a specialized container for organizing your code. You can add things like controllers, directives, and services.

Controllers: The C in MVC, this is the main place you store your application specific business logic used to power views.

Dependency Injection: Angular features a dependency injection system that allows you to create and register injectable modules which can be made available to other parts of your application.

Providers: Angular implements a concept called a provider which can be used alone, or to build Factories and Services which are dependency injectable.

Support for testing: Angular includes support for both unit testing and End-to-End testing. The tools described above aid in making your applications more testable by supporting separation of concerns.

And there's more. However, with Angular you can use as little or as much as you need.

We'll review each of these features later in this presentation.

Pulling it altogether: Angular MVC

Angular support application separation of concerns using MVC and modules such as services and routers

  • M: Model is implemented using the Scope
  • V: Views are real HTML based templates
  • C: Controllers are Constructor functions with access to Model data

In Angular, the Model is implemented using the Scope

The Scope, as we touched on previously is a context for storing data.

Views are simply HTML templates with declarative annotation and data interpolations. I stress the word "REAL" here because other JavaScript functions handle HTML templates as string rather than real DOM elements. This is one of the features which make using Angular more natural than other frameworks.

And lastly, Controllers. Controllers are just plain old JavaScript objects, created using a contructor function. Angular passes the associated Scope to your contructor function along with any other modules you need via dependency injection.

An important concept here is that while you can use as little or as much of Angular as you need, each feature is designed to work together to help you tackle even the most challenging projects.

Data binding

Data binding

  • Allows data to be bound to markup
  • Updated in real-time as data changes

Angular supports the ability to bind data to markup and to bi-directionally update that data when the data changes.

Let's take a closer look.

  !doctype html>
  <html ng-app>
  <head>
  </head>
  <body>
    <div>
      <label>Name:</label>
      <input type="text" ng-model="yourName"
              placeholder="Enter a name here">
      <hr>
      <h1>Hello {{yourName}}!</h1>
      </div>
      <script src="js/angular.min.js"></script>
  </body>
  </html>
    

The ng-model in the <input> markup above is an Angular directive used to bind data an input control

In the example above the ng-model directive is used to bind data to an input control.

The double curly braces (aka mustache tags) allow us to use the bound data.

Let's see a live example:

Name:

Hello !

More fun with data binding

Expressions can be evaluated inside of mustache tags

  <!DOCTYPE html>
  <html ng-app>
  <head>
    <title>DataBinding</title>
  </head>
  <body>
    <h2>Live text: {{ data.message }}</h2>
    <h2>{{ "Hello " + "World!" }}</h2>
    <h2>{{ 2 + 4}}</h2>

    <label>Message: </label>
    <input type="text" ng-model="data.message">

    <script src="angular.min.js"></script>
  </body>
  </html>
    
Source: /samplecode/DataBinding

You can do a lot more with data binding. Inside of mustache tags you can have expressions evaluated.

Those expressions can use data values you define. It's important to note that this isn't JavaScript, they're expressions which Angular parses and makes sense of.

The beauty of this is that has the data values change the page updates without requiring a round trip to a backend server.

Live text:

Hello World!

6

Message:

Data binding and filters

  • Angular enables data filtering
  • Bound expressions can be further processed through a pipe of filters
  • The format is: {{ expression | filter }}
  <!DOCTYPE html>
  <html ng-app>
  <head>
    <title>Data binding and Filters</title>
  </head>
  <body>
     <p>1) Cost: {{ 11.99 + (11.99 * 0.33) | currency }}</p>
     <p>2) Data: {{ 1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z' }}</p>
     <p>3) Lowercase: {{ "Buy Now!" | lowercase }}</p>
     <p>4) Uppercase: {{ "Buy Now!" | uppercase }}</p>
     <p>5) Here is some JSON data: {{ {'Boy':'Fred', 'Girl':'Jill'} | json }}</p>
     <script src="angular.min.js"></script>
  </body>
  </html>
    
Source: /samplecode/DataBindingWithFilters

Introduce filters

currency

capitalization

Here's the output

1) Cost: $15.95

2) Data: 2010-10-29 05:40:23 +0200

3) Lowercase: buy now!

4) Uppercase: BUY NOW!

5) Here is some JSON data: { "Boy": "Fred", "Girl": "Jill" }

Data binding with CSS classes

  <!DOCTYPE html>
  <html ng-app>
  <head>
    <title>DataBindingWithClasses</title>
    <style>
      .red { color: red; }  .green { color: green; }  .blue { color: blue; }
    </style>
  </head>
  <body>
    <h1 class="{{ data.classColor }}">Basic Angular App</h1>
    <label>Title color: </label>
    <input type="text" ng-model="data.classColor">
    <script src="angular.min.js"></script>
  </body>
  </html>
    
Source: /samplecode/DataBindingWithClasses

There's a lot more we can do with data binding. But we'll need to move on...

Let's try it!

Data Binding with Classes

Title color:

Notice anything missing?

  • The HTML is clean, there are no class or id's on the markup
  • We didn't write any JavaScript
  • There was no need to write event handlers

What is this magic?

You may have noticed that our previous examples were missing a few things we've all taken for granted.

Absent from the examples are that there are no HTML class or id's

Also, we haven't written a single line of JavaScript and we didn't have to register any event handlers to support the data binding

What is this magic? We'll see how this works a bit later.

Scope

  • A scope is a JavaScript object
  • Angular assigns a default scope to each angular application
  • Like plain old JS objects, it can hold data, functions, watch expressions and fire events

Angular employs a concept called Scope. In many ways Scope is the glue that binds many Angular features.

Scope is an execution context used to hold data, functions and perform tasks such as watching expressions for changes and firing events.

Beginning Angular developers sometimes confuse scope with their data models. Instead scope is a place where a data model can be stored and shared.

Here's a simple Scope

  <!DOCTYPE html>
  <html ng-app ng-init="data.message='Hello, from your application scope.';">
  <head>
    <title>Simple Scope</title>
  </head>
  <body>
    <h2>Scope says: {{ data.message }}</h2>
    <script src="angular.min.js"></script>
  </body>
  </html>
    
Source: /samplecode/SimpleScope

Understanding Scope

  • A Scope starts its life as a JavaScript object
  • Angular then extends it with additional functionality
  • A Scope can be nested within another scope
  • Scopes can be passed around an application and shared

A scope is a JavaScript object.

In the last slide we talked about scope being a JavaScript object, however we also learned the scope include helper function to perform various data binding related tasks.

Angular does this by extending plain JS objects with its own scope object. This retains the data and functions you've added to your scope in addition to the one's Angular has added.

Discuss RootScope and Scope

https://github.com/angular/angular.js/wiki/Understanding-Scopes

Advanced Scope concepts

  • A Scope can broadcast and receive events
  • A Scope can watch expressions and respond to changes

Directives Revisited

Extending HTML

With Angular we can define our own element as I did below with the my ph-panel directive:

  <ph-panel title="This is the panel's title">
    <p>This is the panel's body.</p>
  </ph-panel>
    

Not only does Angular include a large collection of directives, it also allows developers to build their own custom directives.

In this example we see a ph-panel directive which converts the markup into a styled panel complete with a title and body area.

Notice how we can provide the ph-panel with a title attribute.

Here is the live code using the ph-panel directive:

This is the panel's title

This is the panel's body.

A few extra lines for good measure

A few extra lines for good measure

A few extra lines for good measure

A few extra lines for good measure

Source: /samplecode/ph-panel

In Angular, the topic of directives is a large one. In fact, Alex Vanston wrote "Angular Directives", an entire book which explore directives

Angular Modules

  • Angular provide Modules as a way of organizing our code
  <!DOCTYPE html>
  <html ng-app="myApp">
  <head>
    <title>Simple Angular Module</title>
  </head>
  <body>
    <script src="angular.min.js"></script>
    <script src="app.js"></script>
  </body>
  </html>
  
  angular.module('myApp', []);
  
Source: /samplecode/SimpleModule

Angular provides Modules as a place to group functionality whereby allowing you to organize your code while abiding by best practices such as not polluting the global namespace

In the first listing above we see that we have now specified a name value to ng-app. This let's angular know that we have an Angular application module called myApp

In our app.js file we simply call the module function on the Angular object passing it the name of our module and an empty array.

The empty array is a placeholder to specify any dependencies our module might have.

An important takeaway here is that there is global angular object which was introduced when we loaded angular on our HTML page using the script element.

When angular loaded it looked for the ng-app data attribute (aka directive) and found that we provided a named application module called myApp.

Lastly, we created a module in our app.js file.

We'll revisit modules a big later.

Controllers

  <!DOCTYPE html>
  <html ng-app="myApp">
  <head>
    <title>Simple Controller</title>
  </head>
  <body >
    <div ng-controller="myFirstController">
      {{data.message}}
    </div>
    <script src="angular.min.js"></script>
    <script src="app.js"></script>
  </body>
  </html>
  
  angular.module('myApp', [])
    .controller('myFirstController', function($scope) {
      $scope.data = {
        message: 'Hello from a simple controller!'
      };
    });
  
Source: /samplecode/SimpleModule

Another organizational feature angular provides is controllers.

In controllers we can implement our applications business logic and is the C in Model View Controller paradigm.

We specify controllers in our HTML markup using the Angular ng-controller directive.

In our example here we've added the ng-controller directive to a div element.

This means that the controller named myFirstController will operate on the div element and anything inside of it.

We say that the myFirstController is scoped around or to the div element.

Angular actually creates a new scope for our controller to use.

Notice that we have a data bound expression (there's that curly mustache again) around data.message.

We defined data.message in our controller using the code shown in the second code listing.

There we've simply called the angular object's controller function to define our new controller.

The second parameter to controller is an anonymous function which includes a $scope parameter.

Angular is responsible for invoking our anonymous function and passing a new scope to our controller.

From that point on we're able to attach data and functions to our scope object for use in data binding and other operations.

You see how I've chained the controller call to the result of the module call above.

As you can see, Angular object functions are chainable. But why did I do this?

Controllers and Scope

Using a chrome plugin called Batarang we can see that Angular did indeed create a new scope. Scope 003.

Here we see the data object we created to include our message.

This screen shot also reveals an important point, that scopes can be nested.

Because scopes are essentially JavaScript objects they can be inherited.

If we defined one controller within another, the second one would inherit the values of the first,

but the first would not have access to the inner scope of the nested controller.

Chaining to modules

  var myApp = angular.module('myApp', []);
  myApp.controller('myFirstController', function($scope) {
    $scope.data = {
      message: 'Hello from a simple controller!'
    };
  });
  
  angular.module('myApp', [])
    .controller('myFirstController', function($scope) {
      $scope.data = {
        message: 'Hello from a simple controller!'
      };
    });
  

After all, I could have just done this instead of chaining.

Chaining is cleaner as it doesn't create a new global variable called myApp which needs to be passed around.

Again, Angular is all about best practices!

Nested controllers and Scope (HTML)

  <div ng-controller="myFirstController">
    <p>FIRST CONTROLLER<br>
    First controllers message: [ {{data.message}} ]<br>
    Second controllers message: [ {{data2.message}} ]<br>
    Third controllers message: [ {{data3.message}} ]</p>

    <div ng-controller="mySecondController">
      <hr>
      <p>SECOND CONTROLLER<br>
      First controllers message: [ {{data.message}} ]<br>
      Second controllers message: [ {{data2.message}} ]<br>
      Third controllers message: [ {{data3.message}} ]</p>
    </div>
  </div>

  <div ng-controller="myThirdController">
    <hr>
    <p>THIRD CONTROLLER<br>
    First controllers message: [ {{data.message}} ]<br>
    Second controllers message: [ {{data2.message}} ]<br>
    Third controllers message: [ {{data3.message}} ]</p>
  </div>
    
Source: /samplecode/NestedControllers

Ok, let's get back to our regularly schedule program.

In our earlier examples we saw how controllers get a scope passed into them.

But what happens when controllers are nested? And how does scope visibility come into play?

In this example we define three controllers myFirst, Second and Third Controller

Our second controller is nested inside of our first controller, while the third controller outside of both

Before we discuss how this impacts scope, let's look at how we define our three controllers in JavaScript

Nested controllers and Scope (JavaScript)

  angular.module('myApp', [])
    .controller('myFirstController', function($scope) {
      $scope.data = {
        message: 'Hello from the first controller!'
      };
    })
    .controller('mySecondController', function($scope) {
      $scope.data2 = {
        message: 'Hello from the second controller!'
      };
    })
    .controller('myThirdController', function($scope) {
      $scope.data3 = {
        message: 'Hello from the third controller!'
      };
    });
    
Source: /samplecode/NestedControllers

So here we chain our three controllers to our Angular application module.

In each controller we add a data item with a custom message.

Notice that there isn't any nesting specified here! This is only definition

Nesting is specified in a declarative manner in our HTML.

Let's use Batarang to examine scope behaviors.

At the top, we see the output from our three controllers

Each tries to display the data.message(x) value from its accessible scope.

The goal is to determine what scope data each controller has access to.

The first controller has access to its own message but can't see the message of it's nested (child) controller, nor the value of the third and sibling controller.

The second controller which is nested inside of the first controller, inherits visibility to it's parent's (outter) controller message and as expected has access to its own message.

The third controller is outside of both the first and second controller and thus only see's its own scope message.

The Angular Batarang plugin shows how the scopes are setup and visually confirms the nesting relationships

Controllers and methods

!Function.prototype

The last controller topic we'll examine concerns methods and scopes

We learned that an Angular Controller is a JavaScript constructor function.

So you might expect to use prototypical inheritance to setup member functions.

However that's not really the Angular way.

In Angular, controllers are used to setup the initial state of a scope and to add behaviors to the scope.

This is especially useful as it means that methods can be made accessible to directives and other controllers which might have visibility into the scope.

When you need to create lots of functions to organize your code, you should do so in a provider, service, or factory.

That will help avoid creating monolithic controllers which simply attach lots of functions to a scope.

Dependency Injection

  angular.module('myCoolApp', []);
  
  angular.module('myCoolApp', ['ngRoute']);
  
  angular.module('myCoolApp', ['ngRoute']);
    .config(function($routeProvider) {
      'use strict';
      $routeProvider
        .when('/', {
          templateUrl: 'views/main.html',
          controller: 'MainCtrl'
        })
        .otherwise({
          redirectTo: '/'
        });
    });
  

Dependency Injection is a design pattern that describes how a components can receive their dependencies

This prevents needing complex component loaders and methods of resolving circular dependencies.

The gist of this is that a dependency injection system provides methods for registering components and then passes those components where they are required.

A benefit of this is that components don't have to manage locating other components - they're simply available when needed.

Lets have a closer look at this. Earlier we saw how we create our Angular application module using the following code.

The empty array on the right meant that we were not requiring any dependencies for our app.

However, lets say that we wanted to take advantage of Angular's view routing mechanism.

All we need to do is specify ngRoute in our array of dependencies.

Then we'll write code which uses the ngRoute dependency and configure our application's routes.

You can see here that the first parameter to the application config function is $routeProvider.

Angular takes care of ensuring that it passes an ngRoute provider to the anonymous function.

We simply use it without having to load it ourselves.

We'll continue discussing dependency injection in the next section on Angular Providers.

Providers

  • Angular has a concept called providers which is also used to implement factories and services
  • Using them promotes cleaner and more testable code
  • And better yet, they're injectable!

Angular has a concept called providers which is used to implement factories and services.

This allows you to build reusable library-like components with their own function API.

They help promote cleaner and better structured code which is both maintainable and testable.

Much of the functionality that Angular offers comes to us via providers.

We're encouraged to not only leverage the existing providers, but also to create our own.

Part of the power behind Providers is that they automatically link to the dependency injection system making it easy for you to use your providers, services and factories.

Simple Service and Factory

HTML

  <!DOCTYPE html>
  <html ng-app="myApp">
  <head>
    <title>Simple Service and Factory</title>
  </head>
  <body >
    <div ng-controller="myController">
      <p>Get User from Service: {{ userFromService }}</p>
      <p>Create new user from Factory: {{ createUserWithFactory('Anatoly', 'Karpov') }}</p>
      <p>Create another new user from Factory: {{ createUserWithFactory('Magnus','Carlsen') }}</p>
    </div>
    <script src="angular.min.js"></script>
    <script src="app.js"></script>
  </body>
  </html>
    
Source: /samplecode/SimpleServiceAndFactory

Here is the HTML for our simple service and factory example.

The first paragraph element simply displays the userFromService data item from the current scope.

The second and third paragraphs call two functions defined on the scope.

This is basically what we're already familar with.

Simple Service and Factory

JavaScript

  angular.module('myApp', [])
    .controller('myController', ['$scope', 'FirstService', 'FirstFactory',
      function($scope, myFirstService, myFirstFactory) {
        $scope.userFromService = myFirstService.getUser();
        $scope.createUserWithFactory = function(firstName, lastName) {
          var user = myFirstFactory.createUser(firstName, lastName);
          return JSON.stringify(user);
        };
    }])
    .service('FirstService', function() {
      var user = {
        "firstName": "Garry",
        "lastName": " Kasparov"
      };
      this.getUser = function() {
        return JSON.stringify(user);
      };
    })
    .factory('FirstFactory', function() {
      return {
        createUser: function(firstName, lastName) {
          return {
            "firstName": firstName,
            "lastName": lastName
          };
        }
      };
    });
    
Source: /samplecode/SimpleServiceAndFactory

The JavaScript portion is much more interesting.

Here we define our controller. The big difference here is that we pass FirstService and FirstFactory string into our controller definition.

This is dependency injection at work. Angular looks for providers which we've defined by those names.

Just below our controller we see a service definition. Noticed that it isn't very different from controllers we've created.

Our FirstService returns an object which has a getUser member. Services are essentially singltons which return data which they create or already hav access to.

The object services return is created once and return however many times it's called.

Keep in mind that this doesn't mean services return the same data when its functions are called... only that the object they return is created once.

Factories are different in that Angular creates a new object to return each time. If invoked twice, each object returned will be a new instance.

Simple Service and Factory

Output

  Get User from Service: {"firstName":"Garry","lastName":" Kasparov"}

  Create new user from Factory: {"firstName":"Anatoly","lastName":"Karpov"}

  Create another new user from Factory: {"firstName":"Magnus","lastName":"Carlsen"}
    

Here's the output from our Service and Factory program.

So what then is a provider?

  • A service is a module which returns a single instance of an object
  • A factory is a module which returns a new object each time it's referenced
  • So what then is a provider?
  • A provider is a module which is more comprehensive than a service or factory and can be configured before it's made available

We discussed that Angular has providers, services and factories

A provider is a module which Angular users to implement services and factories.

When you ask Angular to create a service it essentially uses a provider to create it. The same for when you requested a factory.

So, services and factories are nothing more than syntax sugar (i.e. simpler versions) of providers.

Providers themselves are more powerful in that they can behave differently than a service or factory and can be configured before they're made available.

Let's take a look at creating and configuring our own provider.

StartDate Provider

HTML

  <!DOCTYPE html>
  <html ng-app="myApp">
  <head>
    <title>Provider</title>
  </head>
  <body >
    <div ng-controller="myController">
      <p>Get start Date: {{ startDate }}</p>
    </div>
    <script src="angular.min.js"></script>
    <script src="app.js"></script>
  </body>
  </html>
    
Source: /samplecode/Provider

The HTML itself isn't special. Let's look at the app.js file.

StartDate Provider

JavaScript

  angular.module('myApp', [])
    // controller
    .controller('myController', ['$scope', 'StartDate',
      function($scope, myDateProvider) {
        $scope.startDate = myDateProvider.getStartDate();
      }])

    // provider
    .provider('StartDate', function() {
      this.startDate = new Date();
      this.$get = function() {
        var startDate = this.startDate;
        return {
          getStartDate: function() {
            return startDate;
          }
        };
      };
      this.setStartDate = function(newDate) {
         this.startDate = newDate;
      };
    })

    // config
    .config(function(StartDateProvider) {
      //StartDateProvider.setStartDate(new Date("October 13, 1975 11:13:00"));
    });
    
Source: /samplecode/Provider

Ok, so we start with our controller. Notice that we're passing a string named StartDate

That's the name of our provider.

Within our controller we assign the value of calling the start date provider's getStartDate member to the startDate data item on the current scope

Next we define our StartDate provider

Now this is different from how services and factories are setup. We assign an anonymous function to a $get object member.

Like a factory the code assigns a function which returns a function. This allows for data members which are not visible outside this clousure.

When a provider is injected into a controller Angular actually returns the $get function directly.

Which should I use?

So when do I use a service, factory or provider?

  • Services: login and user profile management services
  • Factories: birds for your angry birds clone
  • Providers: when services or factories just won't do

Services make good managers. Use them when you have data or functionality where a single instance of it will surfice accross your application.

A good example is login (signin) service. Another is a user profile management service.

Factories, when you need instances of objects. Think: birds for your angry birds clone.

Providers, when you need need control then a service or factory can provide or when you need control over how it's created and configured.

Best practices

  • Review online style guides and best practices
  • Project structure
  • HTML markup

So this:

    <input class="ipt" type="text" placeholder="name" require ng-model="user.name">
      

Rather than this:

    <input require class="ipt" ng-model="user.name" placeholder="name">
      

Let's look at a few angular best practices. Visit online style guides for more suggestions, and adapt a style that meets your project's needs.

Angular offers lots of ways to organize your code, using directives, controllers, providers, filters, views, and models.

Under your project's root folder make sure to create folders for each of the above.

That is, organize your code into folders to hold your directives, controllers etc..

Another approach for code organization is to organize by application features. So all of the components relating to user profiles might be stored in the same folder.

Whatever you do, make sure your project is locally organized and maintainable.

Keep your markup clean. Add Angular specific directives at the end of elements.

Best practices (cont)

  • Angular uses the ng- prefix as a namespace
  • It also prefixes the $ symbol in front of its providers, modules and services
  • Best to avoid using those in your own code

As we prepare to explore Angular code keep in mind that Angular prefixes its directives with the an NG prefix.

People often ask why the ng prefix? The reason is because NG sounds more like Angular than AN or AG.

Also, and this is somewhat unfortunate for jQuery developers, Angular prefixes many of its services with a dollar symbol.

If I had to guess, and this may be a real strength... the $ symbol could stand for the S in service.

It should go without saying that you shouldn't use these in your own code.

Best practices (cont)

  • Use a consistent naming convention
  • Use JavaScript style naming conventions, after all this isn't Python or Ruby
  • Modules, Directives, Filers should be named lowerCamelCase
  • Controllers should be named UpperCamelCase
  • Factories should be named UpperCamelCase, but Services should be lowerCamelCase

You may have noticed a pattern in the above naming conventions.

Anything that involves a constructor has an uppercase letter prefix.

Best practices (cont)

  • Automate your workflow using tools like Yeoman
  • Don't use globals. Resolve all dependencies using Dependency Injection
  • Do not pollute your $scope. Only add functions and variables that are being used in the templates
  • Do not pollute your controllers. Consider what functionality should be moved to services, factories and providers

Best practices (cont)

  • Don't manipulate the DOM inside of your controllers
  • DOM manipulation should be done in directives
  • Don't scatter backend (AJAX) calls throughout your controllers, put those in services.
  • Prefer Angular providers over external ones.
  $timeout instead of setTimeout
  $interval instead of setInterval
  $window instead of window
  $document instead of document
  $http instead of $.ajax
    

Debugging an Angular application

Testing with Angular

  • We can use Karma to test our Angular code
  • Install Karma from: http://karma-runner.github.io/
  • Karma can execute Jasmine BDD style tests
  • For end-to-end tests Angular has a tool called Protractor

We can use Karma to test our Angular code

To use Karma in your own app follow the instructions on the Karma GitHub repo.

However, if you're running the tests included with this presentation then Karma will be installed when you run npm install.

Karma executes Jasmine BDD style tests and works with other testing frameworks like Mocha and QUnit.

For end-to-end tests Angular has a tool called Protractor

Structure of aJasmine test

  describe('Simple Test Spec', function() {
    it('should just pass', function() {
      expect(true).toBe(true);
    });
  });
    
  • Just JavaScript which calls Jasmine test framework code
  • Each test has three main blocks: describe, it and expect
  • Learn more about Jasmine at http://jasmine.github.io
Source: samplecode/SimpleTest/simpleTestSpec.js

A Jasmine test suite is called a Spec.

So, all of our tests will end in *Spec.js

This isn't absolutely necessary, but it's the default Karma setup for Jasmin.

Jasmine test consist of a describe block which

A Jasmine test is just a JavaScript file which calls functions in the Jasmine Testing Framework

A test file consist of three main blocks.

The describe block describes a test suite. Notice that it simply has two parameters. A text label and an anonymous function.

The describe block also encases one or more "it" sections.

An "it" block defines a behavior - that is what should behavior should the test exhibit

Inside of an "it" block you'll add one or more expecations. That is what assertions should the behavior exhibit?

Running our test

  • Run npm install on this project's root folder
  • At the terminal prompt just run: ./karma_start.sh
  ~/AngularPresentation$ ./karma_start.sh
  INFO [karma]: Karma v0.12.16 server started at http://localhost:9876/
  INFO [launcher]: Starting browser Chrome
  INFO [Chrome 35.0.1916 (Mac OS X 10.9.3)]: Connected on socket Q47fUfs2QdHA5DNhAjXi with id 33541008
  Chrome 35.0.1916 (Mac OS X 10.9.3): Executed 1 of 1 SUCCESS (0.01 secs / 0.008 secs)
    

First make sure you've run npm install on this project's root folder

That will ensure that both Grunt and Karma are installed

At the terminal prompt just run: ./karma_start.sh

You should see output similar to the session shown here.

Broken tests

  • Normally in start with tests that fail
  • Let's make sure we can detect failed tests
  describe('Simple Test Spec', function() {
    it('should just pass', function() {
      expect(true).toBe(false);
    });
  });
    
  INFO [watcher]: Changed file "/Users/cjus/dev/cjus/AngularPresentation/samplecode/SimpleTest/simpleTestSpec.js".
  Chrome 35.0.1916 (Mac OS X 10.9.3) Simple Test Spec should just pass FAILED
          Expected true to be false.
          Error: Expected true to be false.
              at null.<anonymous> (/Users/cjus/dev/cjus/AngularPresentation/samplecode/SimpleTest/simpleTestSpec.js:3:18)
  Chrome 35.0.1916 (Mac OS X 10.9.3): Executed 2 of 2 (1 FAILED) (0.032 secs / 0.028 secs)
    </anonymous>

Normally in Test Drive Development we start with tests that fail

so let's let break our current test

To do this let's change our test expectation toBe false

The

Dependency injection and testing

  • DI makes testing Angular possible

One of the great benifits of Angular's Dependency Injection system is that it make testing your application possible.

The reason is that we can can inject our modules into our Jasmine tests with very little work.

Let see how this works.

Testing Angular

  describe('Angular element and expression test', function() {
    var element
      , $scope;

    beforeEach(module("myApp"));
    beforeEach(inject(function($compile, $rootScope) {
      $scope = $rootScope;
      element = angular.element("<div>{{2 + 2}}</div>");
      element = $compile(element)($rootScope);
      $scope.$digest();
    }));

    it('should equal 4', function() {
      expect(element.html()).toBe("4");
    });
  });
    

Testing Angular involves introducing a few extra steps into our Jasmine files

In this particular test we're testing an angular expression within an element.

As we learned earlier, Angular expression and directives use the scope for data binding.

So in our test we need to inject the $rootScope, we also need to use the $compile provider to actually compile the expression.

For the most part, this sort of thing happens behind the scenes in Angular apps but we need to do it here because we're working in an isolated test context.

And finally, we need to run the $digest() member on the $scope object. This is something we haven't seen in this presentation but essentially, it runs Angular's internal digest cycle where it updates bindings.

Notice that all of that is wrapped in an inject block and beforeEach. The inject handles the dependency injection, in this case for the $compile and $rootScope providers.

The beforeEach ensures that this block is executed before each "it" behavioral test.

Testing controllers

  describe('Angular controller test', function() {
    var myController
      , scope;

    beforeEach(module("myApp"));
    beforeEach(inject(function($controller, $rootScope) {
      scope = $rootScope.$new();
      myController = $controller('myController', {
        $scope: scope
      });
    }));

    it('should have a getDate function which returns a date', function() {
      expect(scope.getDate()).not.toBeNull();
    });
  });
    
Source: samplecode/ControllerTest

Here we have a spec for testing a controller which returns a date.

Here again we ensure that our myApp is available.

Next we inject the $controller and $rootScope providers in order to create a new scope for our controller

We create our controller using the $controller provider and assign our newly created scope.

Now we're ready to test that calling the getDate() member of the scope does indeed return something.

An important point to consider when testing controllers is that we're not really testing the controller but rather the changes it made to its scope.

Testing services

  describe('Angular service test', function() {
    var Base64Service;

    beforeEach(module("myApp"));
    beforeEach(inject(function(_Base64Service_) {
      Base64Service = _Base64Service_;
    }));

    it('should correctly encode a known message', function() {
      expect(Base64Service.encode('Hello from a simple controller!')).toBe('SGVsbG8lMjBmcm9tJTIwYSUyMHNpbXBsZSUyMGNvbnRyb2xsZXIlMjE=');
    });
  });
    
Source: samplecode/ServiceTest

Testing services is straightforward.

We simply inject our service an test its members.

End to end testing using Protractor

Tools for Angular

Angular and Friends

Google members have written a number of excellent tools which support AngularJS development

  • Karma: A test runner for Angular
  • Yeoman: A set of tools which provide code generation, package management and build support (tasks execution)
  • Protractor: An end to end testing framework for Angular which uses Selenium and WebDriverJS
  • Batarang: A chrome plugin which allows you to inspect Angular as it runs

How does Angular work?

TODO: Angular life cycle

Thinking about your application in terms of Angular

Breaking down your application

  • Separate your app into modules, models, controllers, directives, and services

The Angular Story

  • Created in 2008 and 2009 by Miško Hevery and Adam Abrons
  • Goal: to simplify building web applications using an online JSON storage service
  • Business scrapped and code released as open source project

AngularJS was created in 2008 and 2009 by Miško Hevery and Adam Abrons

The two set out to build an online JSON storage service which they hosted under GetAngular.com

The value proposition was to simplify building online applications with pay as you go data storage.

They eventually decided to scrap the business venture, but Angular continued to evolve and was eventually open sourced.

Adam left the project, but Misko pressed on while working at Google

  • At Google, Misko joined the Google Feedback project
  • At one point Misko claimed he could rewrite the product in two weeks using Angular
  • Google Feedback had 17,000 lines of code developed

At Google, Misko meet Brad Green who recruited him to work on the Google Feedback project

The project was difficult to work with and at one point Misko claimed he could rewrite the product in two weeks using his personal side project, called Angular

At the time Google Feedback had 17,000 pnes of code developed over six months by three developers

Brad took Misko up on this offer and Misko didn't quite pull it off.

  • Using Angular, Misko reduce the code from 17,000 lines to 1500 lines of code
  • This success lead to open sourcing the early Angular project
  • External developers start to take notice of Angular

Instead it took him three weeks to rewrite the product and reduce the codebase from 17,000 lines to just 1500 line of code

Based on this success, Brad recommended open sourcing the early Angular and recruiting other Googlers to join the project

Because the project was open sourced, developers outside of google took notice of the project and started using and contributing to it

  • Marc Jacobs from the Google DoubleClick team takes notice
  • He decides to compare Angular and Google's own GWT during one of his team's sprints
  • Angular proved easier to use

One such person turned out to be another Googler, Marc Jacobs from the Google DoubleClick team

Marc was part of the Google acquisition of DoubleClick and was tasked to convert a DoubleClick app from Microsoft .NET to the Google Platform

Marc, impressed by Angular, devoted a two week sprint to trying the conversion using two parallel approaches: 1) Using AngularJS 2) Using Google's GWT

Two days into the sprint he completed the project using Angular. Then he tried the same project using GWT and after five days he gave up on it.

2013, the Angular team hosted an internal conference at Google offices

Initially, 50 people were expected to attend

197 attendees showed up

In October of 2013, the Angular team hosted an internal conference at Google in Mountain View, CA

They expected around 50 people would attend

When the conference started there were 197 attendees, presenting 101 project within Google

  • Angular gained traction inside and outside of Google
  • The Angular team compares Angular's emerging popularity relative to other popular frameworks

Angular was gaining traction inside and outside of Google

The Angular team started tracking how often developers searched for angular relative to other popular frameworks

The team announced that by mid-2013 the popularity of Angular skyrocketed in comparison to other frameworks

At the 2014, first ever AngularJS conference, Brad and Misko announced that by mid-2013 the popularity of Angular skyrocketed in comparison to other frameworks

A few Angular tidbits

Why is it called Angular?

Named after the HTML angled bracket

People often ask why the name Angular? AngularJS focuses on HTML markup which contains angled brackets

So Angular was named after the HTML angled brackets

Why is the logo a shield with a letter "A" on it?

  • Logo chosen because the shield resembles the HTML5
  • Misko felt that the shield represents Angular shielding developers from the low-level differences among web browsers

The logo was chosen because the shield resembles the HTML5 logo which also uses a shield and Angular runs on top of HTML5

Also Misko liked the logo because the shield represents Angular shielding developers from the low-level differences among web browsers

How large is Angular?

You might think all of Angular's features result in a large and bloated framework

Actually, it weighs in at only...

  • 104K minified
  • 38K minified and gzipped
  • To put this in context, jQuery 2.1.1 is 84K minified

The Core Team

  • By early 2014 Angular had 14 core members
  • Google funds Angular development, the top ten contributors on Angular work at Google
  • However, many of the top contributors didn't start off as Google developers but we