Angularjs

From Training Material
Jump to navigation Jump to search


title
Angularjs
author
Lukasz Sokolowski (NobleProg)

Angularjs

Angularjs Training Materials

What is Angular JS? ⌘

  • HTML5, CSS and JavaScript
  • JSON and Ajax
  • Angular JS Applications
  • Models
  • Bindings

Intro ⌘

  • Started in 2009 by Miško Hevery, a Google employee
  • First version 2012
  • Officially supported by Google


  • AngularJS extends HTML with new attributes
  • Great for Single Page Applications (SPAs)
  • Based on simplified jQuery core

Intro con't ⌘

  • JavaScript framework usually added to an HTML page with a <script> tag
  • Extends HTML attributes with Directives
  • Binds data to HTML with Expressions
  • Based on
    • Model View Controller (MVC) methodology
    • Dependency Injection (DI)

Main components ⌘

Idea Explanation
Template HTML with additional markup
Directives extend HTML with custom attributes and elements
Model the data shown to the user in the view and with which the user interacts
Scope context for model accessible by controllers, directives and expressions
Expressions access variables and functions from the scope
Compiler parses the template and instantiates directives and expressions
Filter formats the value of an expression for display to the user
View what the user sees (the DOM)
Data Binding sync data between the model and the view
Controller the business logic behind views
Dependency Injection Creates and wires objects and functions
Injector dependency injection container
Module a container for the different parts of an app including controllers, services, filters, directives which configures the Injector
Service reusable business logic independent of views

https://docs.angularjs.org/guide/concepts

Models ⌘

  • Model binds the value of HTML controls (input, select, textarea) to application data
  • ng-model directive
  • Two-Way Binding
    • when we change the input field, property in angular will also be changed
    • validate the input (type validation: number, e-mail, required)
    • data status (invalid, dirty, touched, error)
    • CSS classes, depending on form field status
      • ng-empty(-not-), ng-touched(-un), ng-valid(-in), ng-dirty, ng-pending, ng-pristine

Bindings ⌘

  • Synchronization between the model and the view
    • both updated at all times, immediately and automatically
    • model changes, view reflects it, and vice versa
  • Model - collection of data available for the application
  • View - html container for application's display
    • has access to model
    • directive ng-bind, binds innerHTML to model property
  • Displaying model data in the view
    • expression {{ }}
    • directive ng-model
  • Controller - steers(adjusts) view via model
    • separated from view

Model and Bindings example ⌘

<!DOCTYPE html>
<html>
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
  <body>
    <!-- Application, View, Directives, Expression -->
    <div ng-app="appy" ng-controller="steery">
      <!-- Directive, Binding to View from Model with Controller-->
      Who are you? <input ng-model="wayField">
      <!-- Binding to View from Model via Expression -->
      <h1>{{ wayField }}</h1>
      <!-- Binding to View from Model via Directive -->
      <p ng-bind="bindMe"></p>
    </div>

    <script>
      // Module
      var app = angular.module('appy', []);
      // Controller with Scope
      app.controller('steery', function($scope) {
        $scope.wayField = "Knock Knock";
        $scope.bindMe = "This one will work.";
      });
    </script>

    <p ng-bind="bindMe">Why this will not work?</p>

  </body>
</html>

Angular way (analysing an above example) ⌘

  • There are no classes or IDs in the HTML to identify where to attach event listeners
  • When 'steery' set the 'wayField' to "Knock Knock" we didn’t have to
    • register any event listeners
    • or write any callbacks
  • 'steery' got the $scope object that it needed without having to create it
  • We didn’t have to call the steery ’s constructor ourselves, or figure out when to call it

Angular way con't 1 ⌘

  • Thanks to MVC our app is easier to extend, maintain, and test
  • Data Binding is the ability to update, part of the DOM separately, rather than updating the whole page
    • We merge template HTML strings with data
    • Then insert the result where we want it in the DOM
      • by setting innerHtml on a placeholder element
    • To insert fresher data into the UI, or change the data based on user input
      • we could just declare which parts of the UI map to which JavaScript properties
      • have them sync automatically to eliminate code when writing our view and model
        • most of the work in moving data from one to the other just happens automatically

Angular way con't 2 ⌘

  • Dependency injection
    • instead of creating dependencies, our classes just ask for what they need
    • 'The Law of Demeter' design pattern (the principle of least knowledge)
      • steery’s job is to set up the initial state for the model
      • it shouldn’t worry about anything else, like how $scope gets created, or where to find it
  • Directives
    • powerful DOM transformation engine that lets us extend HTML’s syntax
    • help us define the view for our app

Expressions ⌘

  • Bind data to HTML
    • double braces: {{ expression }}
    • directive: ng-bind="expression"
  • Resolved and resulted precisely where written
  • Similar to JavaScript expressions
    • can contain literals, operators, and variables
    • can be written inside HTML
    • do not support conditionals, loops, and exceptions
    • support filters

Expressions con't ⌘

  • Simple expressions
  • Values
  • Objects
  • Arrays
  • Maps

Expressions example ⌘

<!-- numbers -->
{{ 1200 + 400 }}

<!-- strings -->
{{ mainUrl + "/" + trainingCategory + "/" + trainingName }}

<!-- objects, with double braces only -->
<div ng-app="" ng-init="training={title:'UML',duration:21}">
  <p>The training title is {{ training.title }}</p>
</div>

<!-- arrays, also with ng-bind -->
<div ng-app="" ng-init="results=[9,7,5,2,8]">
  <p>The second result is {{ results[1] }}</p>
  <p>The fourth result is <span ng-bind="results[3]"></span></p>
</div>

Directives ⌘

  • Extend HTML with new attributes
    • extended HTML attributes with the prefix ng-
  • Lots of built-in directives with plenty of functionalities
  • We can define our own directives

Directives con't ⌘

  • Data typing
  • Looping over arrays and arrays of objects ng-repeat
  • Creating tables, handling selects ng-repeat, ng-options
  • Enabling and disabling HTML elements ng-readonly
  • Hiding and showing HTML elements ng-show, ng-hide
  • Handling HTML events
    • ng-blur, ng-change, ng-click, ng-copy, ng-cut, ng-dblclick
    • ng-focus, ng-keydown, ng-keypress, ng-keyup
    • ng-mousedown, ng-mouseenter, ng-mouseleave, ng-mousemove, ng-mouseover
    • ng-mouseup, ng-paste
  • Custom Directives

Directives example ⌘

<!-- looping with arrays -->
<div ng-app="" ng-init="courses=['UML','Drupal','MongoDB']">
  <p>My favourite courses:</p>
  <ul>
    <li ng-repeat="c in courses">
      {{ c }}
    </li>
  </ul>
</div>

<!-- looping with objects -->
<div ng-app="" ng-init="courseEvents=[
{venue:'London',country:'United Kingdom'},
{venue:'Warsaw',country:'Poland'},
{venue:'HongKong',country:'China'}]">
  <p>Course events:</p>
  <ul>
    <li ng-repeat="ce in courseEvents">
    {{ ce.venue + ', ' + ce.country }}</li>
  </ul>
</div>

<!-- own directive -->
<body ng-app="myOwnDirective">
<!-- as html tag -->
<my-beauty-something></my-beauty-something>
<!-- as html tag's attribute -->
<div my-beauty-something></div>

<script>
var app = angular.module("myOwnDirective", []);

app.directive("myBeautySomething", function() {
    return {
        restrict : "A",
        template : "<h1>My beauty directive!</h1>"
    };
});
</script>
</body>

Controllers ⌘

  • Control the data
  • Regular JavaScript Objects
  • Defined by ng-controller directive
  • Created by a standard JavaScript object constructor

Controllers con't ⌘

  • Defining controllers
  • Object property functions
  • Controller methods
  • Controllers in external files

Controllers example ⌘

<!-- html part -->
<div ng-app="favCars" ng-controller="carsCtrl">

Color: <input type="text" ng-model="car.color"><br>
Max Speed: <input type="text" ng-model="car.maxSpeed"><br>
<br>
Full Name: {{fullDescr()}}

</div>
<script src="carsController.js"></script>
// js part, content of file "carsController.js" 
var app = angular.module('favCars', []);
app.controller("carsCtrl",function($scope) {
    $scope.car = {
        color: "black",
        maxSpeed: "320km",
    };
    $scope.fullDescr = function() {
        var c = $scope.car;
        return "This car is " + c.color + " and can drive at maximum speed of " + c.maxSpeed;
    };
});

Namespaces ⌘

  • Global namespace
  • Modules
  • Module dependencies
  • Library loading
  • Where to put scripts
  • Application files

Modules ⌘

To configure modules in angular we use this interface

Scopes ⌘

  • angular object
  • refers to the application model
  • context in which expressions are executed(evaluated)
  • arranged in hierarchical structure (like DOM of our app)
  • can watch expressions and propagate events

Scopes con't ⌘

  • when we change the model, we can observe it with API ($watch)
  • to change the model not via angular usual ways(ctrls, services, etc), we can propagate it with API ($apply)
  • nesting scopes

Dependency Injection ⌘

  • design pattern
    • how components get hold of their dependencies
  • angular has it's own injector subsystem
    • creates components,
    • resolves component's dependencies
    • provides them to other components as requested

Dependency Injection con't ⌘

  • when we define components
  • in module's .run and .config blocks
    • run - no 'providers'
    • config - no 'service' and 'value'
  • services, directives, filters, and animations
    • injectable factory method or constructor function
    • can be injected with "service" and "value" components (as dependencies)

di and just js ⌘

  • DI is just a big list of key value pairs from which objects are pulled from and passed to our components.
  • The way scopes work is based on prototypical inheritance.
  • The $digest loop is just a task
    • it iterates over expressions and watchers when Angular-related events occur

Filters ⌘

Filters con't ⌘

  • currency number to a currency
  • date date to a specified format
  • filter select a subset of items from an array
  • json an object to a JSON string
  • limitTo limits an array/string, into a specified number of elements/characters
  • lowercase a string to lower case
  • number a number to a string
  • orderBy orders an array by an expression
  • uppercase a string to upper case

Filters example ⌘

<div ng-app="bestB" ng-controller="booksCtrl">

<p>Best books ever:</p>
<ul>
  <li ng-repeat="b in books | orderBy:'title'">
    {{ b.author + ', ' + b.title }}
  </li>
</ul>

</div>

<script>
angular.module('bestB', []).controller('booksCtrl', function($scope) {
    $scope.books = [
        {author:'God',title:'Bible'},
        {author:'Pratchett',title:'Discworld'},
        {author:'Vujcic',title:'Live without the limbs'},
        {author:'Silverberg',title:'We come with dead people'},
        {author:'Lewis',title:'Chronicles of Narnia'},
        ];
});
</script>

HTTP Requests ⌘

  • Reading data from remote servers
    • service $http
    • makes a request to the server, and returns a response

HTTP Requests con't ⌘

  • General requests
  • Shortcuts
    • .delete(), .get(), .head(), .jsonp(), .patch(), .post(), .put()
  • Success and error handling
  • Setting HTTP headers
  • JSON and XSRF vulnerability protection

HTTP Req Example ⌘

<div ng-app="httpReq" ng-controller="httpReqCtrl"> 

<h1>{{content}}</h1>

</div>

<p>Different functions on success and failure.</p>

<script>
var app = angular.module('httpReq', []);

app.controller('httpReqCtrl', function($scope, $http) {
  $http.get("badfilename.htm")
  .then(function(response) {
      $scope.content = response.data;
  }, function(response) {
      $scope.content = "Oh, my .. You can't see the result.. )-: ";
  });
});
</script>

Forms ⌘

  • Data-binding and validation of input controls
  • HTML input control
  • Browser versus Angular JS validation
  • Validating input values
  • Displaying input error messages

HTML input controls ⌘

  • input elements
    • checkbox, radiobuttons, selectbox
  • select elements
  • button elements
  • textarea elements

Form Examples ⌘

<!-- checkbox example -->
<form>
    Do you like it? :
    <input type="checkbox" ng-model="varYes">
</form>
<h1 ng-show="varYes">That's great, it likes you too (-;</h1>

<!-- radiobuttons example -->
<form>
  Do you like it?:
  <input type="radio" ng-model="varYes" value="y">Yes
  <input type="radio" ng-model="varYes" value="n">No
  <input type="radio" ng-model="varYes" value="d">Not sure
</form>

<!-- selectbox example -->
<form>
  Do you like it?:
  <select ng-model="varYes">
    <option value="">
    <option value="y">Yes
    <option value="n">No
    <option value="d">Don't know
  </select>
</form>

<!-- switch for radiobuttons and selectbox examples -->
<div ng-switch="varYes">
  <div ng-switch-when="y">
     <p>Oh, great!</p>
  </div>
  <div ng-switch-when="n">
     <p>What a shame..</p>
  </div>
  <div ng-switch-when="d">
     <p>You sure be more sure (-:</p>
  </div>
</div>

Browser versus Angular JS validation ⌘

  • client-side form validation
  • monitors the state of the form and input fields (input, textarea, select)
  • lets to notify the user about the current state
  • holds information about whether they have been touched, or modified, or not
  • standard HTML5 attributes can also be used to validate input
  • novalidate html5 attribute disables any default browser validation
  • own validation function

Validation Example ⌘

<form ng-app="validApp" ng-controller="validCtrl" name="valForm" novalidate>

  <p>Hero name:<br>
    <input type="text" name="heroInp" ng-model="hero" required>
    <span style="color:pink" ng-show="valForm.heroInp.$dirty && valForm.heroInp.$invalid">
      <span ng-show="valForm.heroInp.$error.required">Hero name is humongously needed!</span>
    </span>
  </p>

  <p>Hero Email:<br>
    <input type="email" name="email" ng-model="email" required>
    <span style="color:red" ng-show="valForm.email.$dirty && valForm.email.$invalid">
      <span ng-show="valForm.email.$error.required">Hey, give me the Email, Mate!</span>
      <span ng-show="valForm.email.$error.email">Oups! Don't cheat!</span>
    </span>
  </p>

  <p>
    <input type="submit" ng-disabled="valForm.heroInp.$dirty && valForm.heroInp.$invalid || valForm.email.$dirty && valForm.email.$invalid">
  </p>

</form>

<script>
var app = angular.module('validApp', []);

app.controller('validCtrl', function($scope) {
    $scope.hero = 'Captain Carrot';
    $scope.email = 'captain.carrot@gmail.com';
});
</script>

Angular Modules ⌘

  • Services
  • Animation
  • REST
  • Cookies
  • Mobile device support

Services ⌘

  • Function, or object, that is available for, and limited to, our AngularJS app
  • Many built-in services
    • $location, $http
  • To use additional service in the controller, it must be defined as a dependency
    • is passed in to the controller as an argument
  • We still can use DOM objects like 'window.location'
    • but it would have some limitations for our AngularJS app
    • angular 'prefers' that we use it's own services
  • Our own service

Service Example

<div ng-app="myApp" ng-controller="myCtrl">
  <p>The url of this page is:</p>
  <h3>{{myUrl}}</h3>
</div>

<script>
var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope, $location) {
    $scope.myUrl = $location.absUrl();
});
</script>

Animations ⌘

  • Animated transitions, with help from CSS (add and remove classes)
  • Transformation of an HTML element gives us an illusion of motion
  • Additional angular Animate library
    • var app = angular.module('myApp', ['ngAnimate']);
      

Animation Example ⌘

<style>
div {
  transition: all linear 0.5s;
  background-color: lightblue;
  height: 100px;
  width: 100%;
  position: relative;
  top: 0;
  left: 0;
}

.ng-hide {
  height: 0;
  width: 0;
  background-color: transparent;
  top:-200px;
  left: 200px;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-animate.js"></script>

<body ng-app="anim">

<h1>Make the magic: <input type="checkbox" ng-model="animCh"></h1>

<div ng-hide="animCh"></div>

Single Page Application Concept ⌘

Router Example ⌘

<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.js"></script>

<body ng-app="routeApp">
<p><a href="#/">Main(iac)</a></p>
<a href="#aboutus">AboutUs</a>
<a href="#contact">Contact</a>

<!-- new Directive from ngRoute library -->
<div ng-view></div>

<script>
var app = angular.module("routeApp", ["ngRoute"]);

app.config(function($routeProvider) {
    $routeProvider
    .when("/aboutus", {
        template : "<h1>We</h1><p>We are the best!</p>"
    })
    .when("/contact", {
        template : "<h1>Contact</h1><p>Forget about my mail and phone number!!</p>"
    })
    .otherwise({
        template : "<h1>Nope</h1><p>Why didn't you try to click on something?</p>"
    });
});
</script>
<body>

Debugging and IDEs ⌘

  • batarang (chrome only)
  • ng-inspector (more browsers)
  • console
    • angular.reloadWithDebugInfo();
    • angular.element($0)
      • angular.element($0).scope()
      • angular.element($0).scope().$parent
    • $scope
  • webstorm, sublime, visual studio, atom

Exercises ⌘


0. Sum up:

In Angular:

(This also references script order for loading)

Module wraps everything in the App.
Controller talks to the View via Model.
Model handles scope (is scope).
Filter sorts the data.
Service sets up for example REST server, or just pure http.
Directive extends html with new Attribute(also tag, css class, comment).
Route serves paths.
Expression binds data between input(user) and the database.





1. Exercise:

Case: How to use value from $rootScope inside our controller?

Do it in two ways (-:

HINT:
- Try to rewrite this example: 
http://www.w3schools.com/angular/tryit.asp?filename=try_ng_scope_rootscope





2. Exercise:
Create small website locally. 
2.1. It should show ordered html list of elements (let's say your 3 favourite movies)
2.2. Use angular and create in the Module application for this "ol"
2.3. Angular should handle gathering data for the all "li" elements in the loop (use proper Directive)
2.4. Angular should use Controller to manage variables
2.5. Use angular to Filter the movies and provide descending order of them
2.6. Make View, which will keep "ol" separated and will be injected in main view(html document)

PLAN:
Create HTML views 
	- Create a module that contains the main view (DATA)
		- Write the controller that helps talk 
                  to the rest of the application

		- Write the Model that contains the $Scope 
		  that  delineates the values (movies)
		
		- Establish the filter and what fields it will
                  filter based on the data - Include an
                  expression to populate the data to the 
		  front end (from the scope)

		- Cut the "ol" from the main view, put it in the angular view and include it via Directive 


2.7. Use inline edit in moviexerc. 

Copy the whole project and create new application, it should keep two modules:
- one for list of movies, 
- second for inline-edit'able title 'List of my fav movies'

Hint:
Try to use this library:
http://vitalets.github.io/angular-xeditable/


2.7.1. Make your app bowerized (-: 

2.7.2. Implement this library in the simplest possible way:
http://www.cssscript.com/demo/beautiful-native-javascript-alert-replacement-sweet-alert/





3. Exercise:

Another website should show some data about potential customer.

It should:
- use controller to provide default data: customer's name 'Naomi',
cutomer's address '1600 Amphitheatre'
- have implemented your own custom angular 'Directive'
and bind/invoke it in all possible ways: attribute, tag, class, comment
-- this directive should be restricted only to tag and attribute
-- test it, try to invoke also as class and comment
- have structure of folders: js, partials(same meaning as views)
- use 'partial html template'(view) with angular 'Expressions'










4. Exercise:

Case: To simplify training coordinator's work 
(compare to example in apache/mysql/php/jquery/drupal shown by trainer)

4.1. Validate polish PESEL field (value example 82010901858):
- PESEL field should be required
- Make sure PESEL is correct (one angular module/controller should be responsible)
HINT: google PESEL algorythm
4.2. Prepopulate dynamically Date of birth field from PESEL field
- get date of birth from it 
(include also algorythm for century 2000-2100, value example 15252305986)
- bind it into Date of birth input field (with this format '1982-01-09'), 
do it dynamically when user type PESEL in first input field










5. Exercise:

Case: Write your own custom filter that title-cased strings for your headings in main html template.














6. Exercise:

Write your custom service, which will find the person with the longest first name 
and longest last name from the list of users.

Use this service in a filter connected to select list field.















7. Exercise:

Case: Write your own custom TODO list.

HINT:
Try to use:
- methods like '.push', '.forEach'
- store data in model (scope)











8. Exercise:

Install another usefull start-up server example: angular seed project.

8.1. git clone --depth=1 https://github.com/angular/angular-seed.git ang_seed
8.2. In 'README.md' find a way to start the server.
8.3. Play with deafult example there (index.html)













9. Exercise:

Case: Create simple 'Mail' app.

9.0. Make it on top of your 'ang_seed' server from the last exercise (no 8)
9.1. It should keep one main view(index.html), second for list of emails(list.html), third for one email(detail.html).
9.2. Controller:
- should keep some fake mails (array of objects: id, sender, subject, date, message) in jsoned variable
- and have simple mapping between URLs, templates and controllers
9.3. Create REST API and 'end-point' in it with jsoned list of emails
- keep list of all mails as 'mails.json' file
- every single mail should have it's own '.json' file
*9.4. Prepare 'add mail' functionality

HINTS: 
Use:
- 'html Table' in 'angular way', 
- routes($routeProvider)
- learn from default example in 'ang_seed'
- for date format use for example this 'Dec 6, 2013 20:35:02'  
- Use pure '$http' service and later improve it with 'angular-resource' library and cerate services with '.factory' 
- make sure your '*.json' files are formed correctly
- if you want to start the http server manually:
-- node node_modules/http-server/bin/http-server -a localhost -p 8000 -c-1 ./app










10. Exercise:

Case: AJAX requests via $http service

Create small app which will get list of emails from the previous exercise.









11. Exercise:

Case: Fix it!

Fix to-do list app in folder 'newtodo00'.