© Luxoft Training. All rights reserved AngularJS Introduction
© Luxoft Training. All rights reserved Why to use HTML5 frameworks Dealwithcross-browser compatibility Makeyourapplicationmorestructured Mayincludereusablecomponents Makeprogrammersmoreproductive Lowertheamountofmanuallywrittencode
© Luxoft Training. All rights reserved Frameworks and Libraries Frameworks expect you to develop using well defined rules. Libraries just offer reusable components There are two major types of frameworks: Feature complete frameworks Lightweight frameworks (MVC + Binding + Routing)
Feature Complete Frameworks Suitable for back-office applications Include a library of UI components Have good tooling Steeper learning curve May be difficult to customize The size of the app 1MB+
Lightweight Frameworks Work best for consumer-oriented websites Can be combined with 3-party libraries Easier to learn Mainly deal with application structure, navigation, AJAX
HTML enhanced for web apps! Here comes… AngularJS
Why AngularJS? Goodchoiceforsingle-pageapplications MVCwithminimalcoding Easyrouting Lightweight,yetpluggablewithwell-definedmodular architecture FollowsmodernWebstandards
© Luxoft Training. All rights reserved Architecture Templating UI widgets/components Avoids DOM manipulation testing modularity, loose coupling and reusability What AngularJS provides?
© Luxoft Training. All rights reserved
© Luxoft Training. All rights reserved Two way data binding example MODEL $scope.name="John“; John Smith Name: ng-model="name" VIEW MODEL $scope.name=="John Smith"; John Name: ng-model="name" VIEW
© Luxoft Training. All rights reserved Scope A scope shares variables between view and controller A scope is a place where the model data are located
Data binding
© Luxoft Training. All rights reserved
© Luxoft Training. All rights reserved Why use a JS MVC framework Poor distribution of processing – With a large number of clients, doing all the processing on the server is inefficient. High user response latency Difficult programming model Increased vector of attack Heavy state management on the servers Offline Difficulties Reduced opportunity for interoperability
© Luxoft Training. All rights reserved Why use a JS MVC framework Scalability - The more clients that use an application, the more client machines that are available, whereas the server processing capabilities remain constant Immediate user response Organized programming model Client side state management Offline applications Interoperability JSMVC Web Applications
© Luxoft Training. All rights reserved Client/server architecture for modern web applications Fullstack JS frameworks contain a mix of the following components: A client side JS framework like Angular/Backbone/Require or other NodeJS as backend application server MongoDB or other document databases based on JS model
© Luxoft Training. All rights reserved Data Flow for modern web development
© Luxoft Training. All rights reserved AngularJS interest: stackoverflow questions
© Luxoft Training. All rights reserved AngularJS interest
Single-Page Application (SPA) No full Web page reloads Only certain pages get refreshed as results of AJAX calls Parts of the page may toggle from visible to hidden using CSS The Web page states doesn’t get reset The user gets a feel of a desktop app The SEO may suffer, need special tricks
Professional SPA features Modularization ControllershandlesDOMmanipulationsandAJAX HTMLtemplating Routingwithdeeplinking RealtimecommunicationviaWebsockets UseofHTML5Localstorage
Hello {{helloTo.title}} ! angular.module("myapp", []).controller("HelloController", function($scope) { $scope.helloTo = {}; $scope.helloTo.title = "World, AngularJS"; } ); Hello World
© Luxoft Training. All rights reserved Scope hierarchy
{{data.theVar}} {{data.theVar}} var module = angular.module("myapp", []); var myController1 = module.controller("myController1", function($scope) { $scope.data = { theVar : "Value One"}; }); var myController2 = module.controller("myController2", function($scope) { $scope.data = { theVar : "Value Two"}; }); $scope Hierarchy
© Luxoft Training. All rights reserved $watch() function $watch() enables to set a callback function to be called whenever the value of a given expression changes: $scope.$watch("name", function(newValue, oldValue) { if ($scope.name.length > 0) { $scope.greeting = "Greetings, " + $scope.name; } }); Template: {{greeting}} In this (simple) case it can be done easier: Template: Greetings, {{name}}
© Luxoft Training. All rights reserved $watch() function More complicated case: $scope.$watch('name', function(value) { var firstSpace = (value || "").indexOf(' '); if (firstSpace == -1) { $scope.firstName = value; $scope.lastName = ""; } else { $scope.firstName = value.substr(0, firstSpace); $scope.lastName = value.substr(firstSpace + 1); } });
…using $scope.$watch()
$digest() cycle $digest evaluates all the $watch expressions in a scope, as well as the scope’s children, and fires the watcher callback on any that have changed
Digest cycle
© Luxoft Training. All rights reserved $digest() var dirty = true; var iterations = 0; while (dirty && iterations++ < TIMES_TO_LOOP) { dirty = false; for (var i = 0; i < scope.watchers.length(); ++i) { var currentValue = scope.watchers[i].get(); if (currentValue != scope.watchers[i].oldValue) { dirty = true; scope.watchers[i].callback(currentValue, scope.watchers[i].oldValue); scope.watchers[i].oldValue = currentValue; } TIMES_TO_LOOP constraint exists to prevent AngularJS from getting stuck in an infinite loop in $digest. If the loop executes more than TTL times, AngularJS throws a 10 $digest iterations reached Aborting! error.
© Luxoft Training. All rights reserved $apply() function informs AngularJS that something has changed and the values of $watch expressions should be recomputed $scope.getWeather = function() { $.get(weatherUrl, function(data) { $scope.weather = data; $scope.$apply(); }); }
document.getElementById("updateTimeButton").addEventListener('click', function() { console.log("update time clicked"); $scope.data.time = new Date(); $scope.$apply(); }); document.getElementById("updateTimeButton").addEventListener('click', function() { $scope.$apply(function() { console.log("update time clicked"); $scope.data.time = new Date(); }); Custom use of $apply()
Data binding event loop ng-model ng-bind
Perfomance of two-way binding Legendary Stanford computer science professor Donald Knuth: “Premature optimization is the root of all evil" AngularJS team informally recommends that you have less than 2,000 watchers on a single page The master ‐ detail pattern usually displays static information in the master list. Suppose your application is a list of upcoming events: You don’t want people browsing events to be able to change the title of any given event! In cases like this, setting a watcher on the event title is a waste because the user should not be able to modify the title anyway.
© Luxoft Training. All rights reserved Standard directives
© Luxoft Training. All rights reserved Standard directives © 2014 Farata Systems 39 A directive is something that introduces new syntax. Directives are markers on a DOM element which attach a special behavior to it. Directives offer: ‣ UI decomposition ‣ Reusable components Examples: ng-app, ng-model
© Luxoft Training. All rights reserved Directive representation in template Can be represented in four flavors: HTML element’s attribute: ng-user HTML element: CSS class: Comment:
© Luxoft Training. All rights reserved AngularJS standard directives
{{myData.textf()}} angular.module("myapp", []).controller("MyController", function($scope) { $scope.myData = {}; $scope.myData.textf = function() { return "A text from a function"; }; }); Interpolation Directive: ng-bind or {{}}
ng-show + ng-hide Directives will be show will be hidden angular.module("myapp", []).controller("MyController", function($scope) { $scope.myData = {}; $scope.myData.showIt = true; });
ng-switch Directive Shown when switch is 1 Shown when switch is 2 Shown when switch is anything else than 1 and 2 angular.module("myapp", []).controller("MyController", function($scope) { $scope.myData = {}; $scope.myData.switch = 3; });
ng-if Directive ng-if Show it angular.module("myapp", []).controller("MyController", function($scope) { $scope.myData = {}; $scope.myData.showIt = true; });
ng-include Directive <div ng-include="myData.showIt && 'fragment-1.html' || 'fragment-2.html'"> angular.module("myapp", []).controller("MyController", function($scope) { $scope.myData = {}; $scope.myData.showIt = true; });
ng-repeat Directive {{theItem.text}} angular.module("myapp", []).controller("MyController", function($scope) { $scope.myData = {}; $scope.myData.items = [ {text : "one"}, {text : "two"}, {text : "three"} ]; }); Special ng-repeat Variables: $index - index of the element being iterated $first, $middle, $last - boolean value depending on whether the current item is the first, middle or last {{$index+1}}) {{theItem.text}}
© Luxoft Training. All rights reserved Directive classes
© Luxoft Training. All rights reserved Filtering data
Filtering angular.module("myapp", []).controller("MyController", function($scope) { $scope.myData = {}; $scope.myData.items = [ {text : "one"}, {text : "two"}, {text : "three"}, {text : "four"} ]; $scope.itemFilter = function(item) { if(item.text == "two") return false; return true; } });
Formatting Filters {{myData.theDate | date: 'dd-MM-yyyy'}} {{myData.theNumber | number: 2}} {{myData.mixedCaseText | lowercase}} {{myData.mixedCaseText | uppercase}}
Array Filters {{myData.theText | limitTo: 3}}
Filtered: {{myData.text | myFilter:2:5}} var module = angular.module("myapp", []); module.filter('myFilter', function() { return function(stringValue, startIndex, endIndex) { return stringValue.substring( parseInt(startIndex), parseInt(endIndex)); }; }); Custom Filters
© Luxoft Training. All rights reserved JavaScript events in AngularJS
AngularJS Event Listener Directives ng-click ng-dbl-click ng-mousedown ng-mouseup ng-mouseenter ng-mouseleave ng-mousemove ng-mouseover ng-keydown ng-keyup ng-keypress ng-change Click here angular.module("myapp", []).controller("MyController", function($scope) { $scope.myData = {}; $scope.myData.doClick = function() { alert("clicked"); } } );
Click here angular.module("myapp", []).controller("MyController", function($scope) { $scope.myData = {}; $scope.myData.doClick = function(event) { alert("clicked: " + event.clientX + ", " + event.clientY); } } ); Event Object passing
<li ng-repeat="item in myData.items" ng-click="myData.doClick(item, $event)">Click here angular.module("myapp", []).controller("MyController", function($scope) { $scope.myData = {}; $scope.myData.items = [{ v: "1"}, { v: "2"}, { v : "3"} ]; $scope.myData.doClick = function(item, event) { alert("clicked: " + item.v + ” + event.clientX + ": " + event.clientY); } } ); Passing parameters to event listener
© Luxoft Training. All rights reserved AngularJS modules
Controllers Handleuserinteractions Createsthemodelvariablesonthe$scopeobject Providedata-bindingsource(model)forviews Receivecontrolduringrouting Nevermanipulatetheviewdirectly Aviewcanhavemultiple controllers
Frequently used AngularJS services $scope-accesstothe current scope current $rootScope-accesstotherootscope $http-HTTPrequests $location-toworkwithwindow.location $window-toaccesswindowobject
© Luxoft Training. All rights reserved