Angular1

Articles
Videos
Resources

https://docs.angularjs.org/tutorial
https://docs.angularjs.org/guide/
https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md
https://angular.github.io/protractor/#/api
https://docs.angularjs.org/guide/filter#using-filters-in-controllers-services-and-directives
https://docs.angularjs.org/api/ng/filter
https://docs.angularjs.org/api/ng/type/angular.Module
https://docs.webplatform.org/wiki/css/properties/animations
https://docs.angularjs.org/guide
https://docs.angularjs.org/api

Pages that I have not printed:
Components
Modules
Some pages under the testing section
Some pages under the example section
Layout templates
Dependency injection
ngRoute

Debugging
Basic / Introduction
Additional cheatsheet
Getting started & tools
Scope
Executing scope functions
Interval
Components
Modules
Expression
Sharing data between controllers
ng-app
ng-view
angular.module
ngRoute
UI Router
Layout templates
Dependency injection
Controllers
Controller As
Factories
ng-repeat
Display filters
Validation
Services
Testing
Event binding
Observables
Start-up phases
Security
Animation

Example 1
Example 2
Example 3
Example 4
Example 5
Example 6

Bower

ngCourse
Questions

Current Activities

https://docs.angularjs.org/guide/scope
https://www.youtube.com/watch?v=2zmUSoVMyRU - 15 tricks to master Chrome Developer Tools Console - done watching
https://www.youtube.com/watch?v=ejBkOjEG6F0 - Learn and Understand AngularJS - The First 50 Minutes - done watching
https://www.youtube.com/watch?v=0kmdjqgO9IY
https://www.youtube.com/watch?v=i9MHigUZKEM
https://www.youtube.com/watch?v=4TM6wG9UW7s
https://www.youtube.com/watch?v=TRrL5j3MIvo

What is Angular JS and why should we use it or not?

Angular is a JavaScript framework that embraces extending HTML into a more expressive and readable format. It allows you to decorate your HTML with special markup that synchronizes with your JavaScript leaving you to write your application logic instead of manually updating views. Whether you're looking to augment existing JavaScript applications or harness the full power of the framework to create rich and interactive SPA's, Angular can help you write cleaner and more efficient code.

AngularJS is a structural framework for dynamic web apps. Angular lets you use HTML as your template language and lets you extend HTML's syntax to express your application's components clearly and succinctly. Angular's data binding and dependency injection eliminate much of the code you would otherwise have to write.

What are the features offered by Angular?

  1. Use data binding to wire up your data model to your views.
  2. Create and run unit tests, with Karma.
  3. Create and run end-to-end tests, with Protractor.
  4. Move application logic out of the template and into components and controllers.
  5. Get data from a server using Angular services.
  6. Apply animations to your application, using the ngAnimate module.
  7. Structure your Angular applications in a modular way that scales well for larger projects.

What are the commands that we need to use if when following the angular-phonecat tutorial?

  1. npm start: Start a local development web server. This will create a local web server that is listening to port 8000 on your local machine. You can now browse to the application at http://localhost:8000/index.html. To serve the web app on a different IP address or port, edit the "start" script within package.json. You can use -a to set the address and -p to set the port. You also need to update the baseUrl configuration property in e2e-test/protractor.conf.js.
  2. npm test: Start the Karma unit test runner. This will start the Karma unit test runner. Karma will read the configuration file karma.conf.js, located at the root of the project directory. This configuration file tells Karma to:
    1. Open up instances of the Chrome and Firefox browsers and connect them to Karma.
    2. Execute all the unit tests in these browsers.
    3. Report the results of these tests in the terminal/command line window.
    4. Watch all the project's JavaScript files and re-run the tests whenever any of these change.
    5. It is good to leave this running all the time, in the background, as it will give you immediate feedback about whether your changes pass the unit tests while you are working on the code.
  3. npm run protractor: Run the Protractor end-to-end (E2E) tests. We use E2E (end-to-end) tests to ensure that the application as a whole operates as expected. E2E tests are designed to test the whole client-side application, in particular that the views are displaying and behaving correctly. It does this by simulating real user interaction with the real application running in the browser. The E2E tests are kept in the e2e-tests directory. The angular-phonecat project is configured to use Protractor to run the E2E tests for the application. Protractor relies upon a set of drivers to allow it to interact with the browser. You can install these drivers by running: npm run update-webdriver. You don't have to manually run this command. Our npm scripts are configured so that it will be automatically executed as part of the command that runs the E2E tests.
  4. npm run update-webdriver: Install the drivers needed by Protractor.
  5. webdriver-manager start: start the WebDriver / Selenium server

When following the angular-phonecat tutorial, what happens when we run the 'npm install' command the very first time?

This command reads angular-phonecat's package.json file and downloads the following tools into the node_modules directory:

  1. Bower - client-side code package manager
  2. Http-Server - simple local static web server
  3. Karma - unit test runner
  4. Protractor - end-to-end (E2E) test runner

Running npm install will also automatically use bower to download the AngularJS framework into the app/bower_components directory. Note the angular-phonecat project is setup to install and run these utilities via npm scripts. This means that you do not have to have any of these utilities installed globally on your system to follow the tutorial.

How can we get started with Angular 1?

Angular comes as a single .js file that needs to be included at the bottom of your HTML page:

https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js

What is the command used to start the local server?

python -m SimpleHTTPServer
python -m SimpleHTTPServer <port>

On OS X, Python is pre-installed and this command works out of the box. To customize SimpleHTTPServer, see http://www.2ality.com/2014/06/simple-http-server.html

What is an Angular directive?

Both ng-app and ng-controller, are Angular directives. Think of an Angular directive as something that allows you to extend your HTML. A directive is essentially a function† that executes when the Angular compiler finds it in the DOM. The function(s) can do almost anything, which is why I think it is rather difficult to define what a directive is. Each directive has a name (like ng-repeat, tabs, make-up-your-own) and each directive determines where it can be used: element, attribute, class, in a comment.

How can we create a simple controller?

<div ng-controller="TestCtrl"><h1>{{title}}</h1>
   <input type="text" ng-model="title">
</div>

<script>
   function TestCtrl($scope) {
      $scope.title = 'Write a title here...';
   };
</script>

In the above code, we specify the name of the controller using the ng-controller directive. Angular will be looking for a function with this name in our JavaScript so that it can act as a Controller. Complete example:

<!doctype html>
<html ng-app>
  <head>
    <title>Sample AngularJS Controller</title>
  </head>
  <body>
    <div ng-controller="TestCtrl">
        <h1>{{title}}</h1>
        <input type="text" ng-model="title">
    </div>

    <script src="lib/jquery-v1.11.1.js"></script>
    <script src="lib/angular-v1.2.22.js"></script>

    <script>
      function TestCtrl($scope) {
        $scope.title = 'Write a title here...';
      };
    </script>
  </body>
</html>

What is the purpose of the ng-view directive?

The ng-view attribute here will tell Angular where we wish to inject HTML based on the URL a user visits. In this sample project, we'll want to have an inbox view. When a user visits the /inbox URL our (yet to be created) inbox.html file would be injected inside the ng-view. The inbox.html file would also have it's corresponding controller (InboxCtrl).

<html ng-app="myApp">
    <head>
    </head>
    <body>
        <div ng-view></div>
    </body>
</html>

Angular encourages the "single page application" methodology, which means we never get a full page refresh, all "pages" are injected content via XHR (Ajax). Of course these aren't "pages" as such, they're "views" - which are loaded depending on the URLs a user visits or the application state.

What is the purpose of the angular.module() method?

angular.module('myApp', []);

Notice the empty array, this is where we could put any other named modules as dependencies. Here we tell angular we're creating the module named 'myApp' with no dependencies. To get a reference to a module we drop the array and just call the module by name:

angular.module('myApp');

How can we include ngRoute as a dependency?

var app = angular.module('myApp', [
   'ngRoute'
]);

How can we bind a Controller to the DOM?

Use the ng-controller directive.

How can we dynamically assign a Controller through the $routeProvider service?

Angular allows you to dynamically assign a Controller through the $routeProvider service, which is much more flexible. From now on let's use this instead of using ng-controller="" to declare Controllers.

What is the purpose of the .config() function?

Angular modules each have a .config() function, we give this a callback that is run before most other function callbacks in Angular. This is where we must configure our routes (the different URLs visitors will be able to access).

app.config(function () {/*...*/});

How can we do routing using $routeProvider?

app.config(function ($routeProvider) {
   $routeProvider
      .when('/inbox', {
         templateUrl: 'views/inbox.html',
         controller: 'InboxCtrl',
         controllerAs: 'inbox'
      })
      .when('/inbox/email/:id', {
         templateUrl: 'views/email.html',
         controller: 'EmailCtrl',
         controllerAs: 'email'
      })
      .otherwise({
         redirectTo: '/inbox'
      });
});

What is the difference between the 'controller' and the 'controllerAs' settings when defining a route?

Later versions of Angular (we're using one of the latest) ship with a new Controller syntax, the "Controller as" syntax, which instantiates the Controller like an Object and binds it to the current scope under a namespace. The namespace we've chosen for InboxCtrl is inbox.

You can also declare "Controller as" in-line. It'd look like this: ng-controller="InboxCtrl as inbox".

How can we connect the model and the view?

Controllers are the middleman between the Model and the View, they drive the Model and View changes. Imagine that the controller is given some html from the route and a javascript object from the dependency injection; with these two things, the controller will tell the view (the html) what it can do by giving it scope variables and maybe a few functions.

What should a good controller look like?

A good Controller will have as little logic in it as possible, and should only be used for two things: Binding the Model to the View (initializing the View) and adding helper functions to the View.

What are the two functions of a good controller?

A good Controller will have as little logic in it as possible, and should only be used for two things: Binding the Model to the View (initializing the View) and adding helper functions to the View.

If you go through the Angular documentation examples (available at AngularJS.org) you'll notice Model data being declared in the Controller. While this is okay for examples, the Controller easily becomes the Model as well - which is very bad for many reasons.

What is the purpose of the .controller() method?

It is another way to define a controller:

app.controller('InboxCtrl', function () {
   // Model and View bindings
   // Small helper function not needed anywhere else
});

What does each controller have access to?

Each controller has access to a $scope and some html. $scope is the most documented way of adding properties and methods to our view. Each 'ng-controller' attribute specifies a scope of HTML to manage? Well, that scope has access to the same $scope as the Controller function.

Note: $scope isn't the only way to pass data to the front end. Many developers use a combination of the "Controller As" configuration options along with the this keyword. For the purpose of this tutorial, we will stick with $scope as it's been around for much longer than 'Controller As'.

app.controller('InboxCtrl', function ($scope) {
   // initialize the title property to an array for the view to use
   $scope.title = "This is a title";
});

Why are we encouraged to always have at least one dot (.) in our view expression properties?

http://stackoverflow.com/questions/17178943/does-my-ng-model-really-need-to-have-a-dot-to-avoid-child-scope-problems

What are Angular Factories used for?

Angular Factories can be used for many different things. Some of the most common use-cases are server-side communication via HTTP and abstracting Models to persist application state and changes across controllers. Angular Factories are a great way to create reusable features and code blocks throughout our application.

You may have heard of factories as a design pattern in many programming languages, but Angular's factories are different to those in practice (maybe not in spirit :). You can create a factory using the angular.factory() method like so:

app.factory('ExampleFactory', function ExampleFactory($rootScope, $http, $location) {
   return function myReusableFunction() {
      // do something fancy
   };
});

It's often good practice to create an exports Object inside your Factories and return it. This helps with explicit internal naming which helps you see which methods / variables are private or not. In this app, we'll need to get our messages, so let's create a function to do that. Angular uses the $http service to communicate with the server, so we'll inject it:

app.factory('InboxFactory', function InboxFactory ($http) {
   var exports = {};

   exports.getMessages = function () {
      return $http.get('json/emails.json')
         .error(function (data) {
            console.log('There was an error!', data);
      });
   };

   return exports;
});

How can we connect our controller together with our factory?

Promises are very important inside Angular, they allow you to organize functions that take a long time to do things (e.g. HTTP requests). Promises in Angular are implemented with $q. The $q implementation was inspired by Kris Kowal's Q.

var deferred = $q.defer();
   deferred.promise.then(
      function whenThingsGoSunny(){},
      function whenThingsDontGoSoSunny(){}
   )

When making HTTP requests in Angular you'll often use the $http service which is based on $q. As we just saw, $q allows you to use .then() to include a success and an error function. When using $http, you can do something very similar (but without the .then():

$http({method: 'GET', url: '/someUrl'})
   .success(function(data, status, headers, config) {
      // this callback will be called asynchronously
      // when the response is available
   })
   .error(function(data, status, headers, config) {
      // called asynchronously if an error occurs
      // or server returns response with an error status.
   });
app.controller('InboxCtrl', function($scope, InboxFactory) {
   InboxFactory.getMessages()
      .success(function(jsonData, statusCode) {
         console.log('The request was successful!', statusCode, jsonData);
         // Now add the Email messages to the controller's scope
         $scope.emails = jsonData;
   });
});

See how the InboxFactory factory is available as an injectable in our controller? That's dependency injection helping us out again! We then call the getMessages method on the factory and using the $http()'s success method ($http() was returned from getMessages()), we can then add the list of emails / messages to our controller's $scope and use it in the view. i.e. The success(fn) is available from chaining when we do http() or http.get(), etc…

What can we put inside our Angular Template expression?

You may have noticed that inside our template we were using the properties that we added to scope directly inside . These are called expressions and we can put some basic JavaScript in there too, as well as a bunch of filters.

<!-- JavaScript inside expression -->
<h1>{{ [ firstName, lastName ].join(" ") }}</h1>
<!-- currency filter applied to a multiplication of 2 numbers -->
<div class="total-info">{{ cost * quantity | currency }}</div>
<!-- Using a ternary expression inside the expression -->
<div class="budget">{{ ( total > budget ) ? "Too Expensive" : "You can buy it!" }}</div>

How can we implement custom HTML element using Angular?

Directives are Angular's take on custom HTML elements. They offer a very reusable way to encapsulate data, templates, and behaviors. In our View file we might have something like this:

<div id="someview">
   {{ data.scopePropertyAsUsual }}
   <my-custom-element></my-custom-element>
</div>

Where the <my-custom-element> above will be injected with our directive template and logic. Here's what the basic directive structure might look like:

app.directive('myCustomElement', function myCustomElement() {
   return {
      restrict: 'EA',
      replace: true,
      scope: true,
      template: [
         "<div>",
         "    <h1>My Custom Element's Heading</h1>",
         "    <p>Some content here!</p>",
         "    <pre>{{ ctrl.expression | json }}</pre>,"
         "</div>"
      ].join(""),
      controllerAs: 'ctrl',
      controller: function ($scope) {
         this.expression = {
            property: "Example"
         }
      },
      link: function (scope, element, attrs) {}
   }
});

As you can see the name of the directive is camelCased (myCustomElement) whereas the html element is hyphen-separated (<my-custom-element></my-custom-element>). This is an angular convention for directive naming.

Next, we return a JavaScript Object with various properties on it to describe how the directive works. Here's a quick run through of what some of the Directive properties mean:

  1. restrict: allows you to restrict how the element is declared, E = Element, A = Attribute, there are other ways of declaring (such as a comment) but I wouldn't recommend them as they're not that friendly with older browsers.
  2. replace: replaces the Directive's root element, in this case would be <inbox></inbox>.
  3. scope: tells Angular to use an isolated or inherited scope, these concepts are quite tricky to grasp, but setting to true inherits the parent scope and keeps sibling directives more independent, which makes things easier to work with. There are cases where isolated scopes (scope: {}) are the better choice depending on what we're doing.
  4. template: I've recently used an [].join('') style for templating, it's much cleaner to work with and we can start the first line of the template on a new line, rather than having a huge indent.
  5. templateUrl: the same as template, but will point to a template file such as tmpl/inbox-directive.html instead of being a string.
  6. controllerAs: creates a namespace for our Controller when instantiated
  7. controller: inject dependencies and bind logic, you may also expose an API for other directives to interact with this one through the 'controllerAs' and this of the controller.
  8. link: a place to write non-Angular logic, but tie it in with Angular. You'll have access to the current scope, the template element root (first element in template rather than Directive root) and the attributes on the element declared.

These are some of the most commonly used properties, though you can check the documentation (found under the $compile section of the API) for other properties. You can also browse Angular's documentation on directives.

In our demo app, here's what our InboxFactory looks like:

angular.module('EmailApp')
   .factory('InboxFactory', function InboxFactory ($q, $http, $location) {
      'use strict';
      var exports = {};

      exports.messages = [];

      exports.goToMessage = function(id) {
         if ( angular.isNumber(id) ) {
            // $location.path('inbox/email/' + id)
         }
      }

      exports.deleteMessage = function (id, index) {
         this.messages.splice(index, 1);
      }

      exports.getMessages = function () {
         var deferred = $q.defer();
         $http.get('json/emails.json')
            .success(function (data) {
               exports.messages = data;
               deferred.resolve(data);
            })
            .error(function (data) {
               deferred.reject(data);
            });
         return deferred.promise;
      };

      return exports;
   });

And here's what our finished Directive looks like:

app.directive('inbox', function () {
   return {
      restrict: 'E',
      replace: true,
      scope: true,
      templateUrl: "js/directives/inbox.tmpl.html",
      controllerAs: 'inbox',
      controller: function (InboxFactory) {
         this.messages = [];
         this.goToMessage = function (id) {
            InboxFactory.goToMessage(id);
         };
         this.deleteMessage = function (id, index) {
            InboxFactory.deleteMessage(id, index);
         };
         InboxFactory.getMessages()
            .then( angular.bind( this, function then() {
               this.messages = InboxFactory.messages;
            })    );
      },
      link: function (scope, element, attrs, ctrl) {
         /*
         by convention we do not $ prefix arguments to the link function
         this is to be explicit that they have a fixed order
         */
      }
   }
});

Now we can use this directive anywhere in our application's scope by creating an <inbox></inbox> element (using restrict: 'E' to specify an element directive).

When the application runs, Angular will replace the <inbox> element with the template at the templateUrl. We then make an alias for the controller under the name of inbox. This alias is then accessible inside the controller as this and inside the template as inbox. If you look inside the template you'll see expressions like inbox.messages and inbox.deleteMessage(id, $index). These are the same this.messages and this.deleteMessage we can see in the InboxFactory.

Finally we have a link function that will run straight after the controller runs. The link function will then receive the aliased controller as the fourth argument, here we named it ctrl. Yes that's right, the link function has fixed positions for it's arguments i.e. scope is always first.

This is different behavior to the controller's arguments which are injected and therefore can take any order. For the link function we don't use the $ prefix for scope, element and attributes to make it clear that they aren't under the control of dependency injection.

Here's the complete HTML template (view) for the directive:

<div class="inbox">
  <div class="inbox__count">
    You have {{ inbox.messages.length && inbox.messages.length || 'no' }} messages
  </div>
  <div ng-hide="!inbox.messages.length">
    <input type="text" class="inbox__search"
      ng-model="inbox.search"
      placeholder="Search by 'from', e.g. TicketMaster">
  </div>
  <ul class="inbox__list">
    <li ng-show="!inbox.messages.length">
      No messages! Try sending one to a friend.
    </li>
    <li ng-repeat="message in inbox.messages | filter:{ from: inbox.search }">
      <div class="inbox__list-info">
        <p class="inbox__list-from"> from: {{ message.from }} </p>
        <p class="inbox__list-date"> {{ message.date | date: 'dd/MM/yyyy' }} </p>
        <p class="inbox__list-subject"> {{ message.subject }} </p>
      </div>
      <div class="inbox__list-actions">
        <a href="#" ng-click="inbox.goToMessage(message.id);">
          Read
        </a>
        <a href="" ng-click="inbox.deleteMessage(id, $index);">
          Delete
        </a>
      </div>
    </li>
  </ul>
</div>

Notice the use of built-in angular directives such as ng-hide, ng-show, ng-click, ng-repeat and ng-model.

What can we use directive for?

Directives are not just custom elements, they are much more… you can use them for all sort of custom logic, especially when you want to reuse some code.

How can we use the ng-show directive?

Our Directives will evaluate based on data. For example ng-show="someData" will evaluate when the value of someData is true. If the value is false, it will hide the element.

What is the purpose of the ng-repeat directive?

One of the most powerful Angular Directives is ng-repeat, which iterates over Objects (or items) in an Array:

<ul>
   <li ng-repeat="item in items">
      {{ item.name }}
   </li>
</ul>

How can we use the ng-model directive?

In our code, we have:

<li ng-repeat="message in inbox.messages | filter:{ from: inbox.search }">

But where did inbox.search come from? Well this was created by the ng-model directive that we attached to an input field:

<input type="text" class="inbox__search" placeholder="Search" ng-model="inbox.search">

Now, whenever someone types into this field, it will set the inbox.search property and update the ng-repeat's filter. Pretty wild, right?!

What is cloacking?

Angular has a really neat built-in feature called cloaking, which you can declare on an Element to tell Angular it needs cloaking (hide it) whilst it's still rendering. Cloaking allows you to hide any handlebars you might see flicker before Angular has rendered and loaded your data. E.g. before the user data has had time to load.

When lib/angular.js has loaded, AngularJS automatically appends an inline <style></style> element to your document with cloaking styles to hide elements during load. This can sometimes take a second to load as it's got a JavaScript dependency too, so I recommend setting up the <head></head> of your document manually like this:

<!doctype html>
<html ng-app="app">
  <head>
    <style>
    [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
      display: none !important;
    }
    </style>
  </head>
  <body>
  </body>
</html>

This is 100% reliable and hide any cloaked elements immediately, even without Angular loaded. Applying cloaked styles is easy:

<div ng-cloak>
   {{ someData }}
</div>

How can we make it easier to debug Angular?

Angular uses a lot of anonymous functions in the call stack. When these throw an error (yes, you'll see a lot of errors during development), to make things easier to debug, I've named anonymous functions. Here it is before:

app.factory('InboxFactory',
   function ($q, $http) {}
):

..and now after:

app.factory('InboxFactory',
   function InboxFactory ($q, $http) { }
):

This will then show errors at InboxFactory rather than at anonymous. A handy tip for developing Angular apps.

How can we make it easier to debug routing problems?

Another debugging tip when working with routes is to listen for Routing Events to be triggered on the $rootScope. A suitable place for this is the run function, found here, which can be thought of as a 'controller for the module', but try to keep this section as small as possible!

app.run(function($rootScope) {
   $rootScope.$on('$routeChangeError', function(event, current, previous, rejection) {
      console.log(event, current, previous, rejection)
   })
});

The above example sets an event listener for any errors that occur during a route change.

Why should we avoid using jQuery especially when using Angular?

When moving from something like website development to Angular you can be tempted to use jQuery selectors (since you already know how to use jQuery). You need to avoid doing that. Angular takes care of DOM manipulation. Do not modify it yourself, unless you really need to or are using a plugin. Anything you'll likely want to do, Angular can do. Getting the value of a textarea? You might be tempted to do this:

<textarea></textarea>
<script>
    var elem = document.querySelector('textarea');
    var value = elem.value;
</script>

With Angular, the ng-model will keep this updated for us, we just reference it:

<textarea ng-model="myModel"></textarea>
<script>
    app.controller('SomeCtrl', function SomeCtrl($scope) {
        // binds and keeps the value updated at all times
       // no need to re-query the value at any time
       // which means we can pass the value straight
       // back to the server for example
       $scope.myModel = '';
    })
</script>
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License