Angular 2 in comparison with Angular 1

VS

  1. Intro
  2. What is Angular (for those who came from the past)?
  3. Angular 2 key features
  4. Comparison

Agenda

Comparison Plan

Core features (Architecture)

Directives

Controllers

Services

Modularity

Template syntax

Misc

DISCLAIMER

All code samples will provided on TypeScript (JavaScript strict typed superset) used by Angular 2 development team and recommended for development of Angular 2 applications. 

Angular 2 releasead!

INTRO

Angular

So, what is it?

how it's working?

What is all about?

MV*, MVW

AngularJS is a structural framework for dynamic web apps. It 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. And it all happens within the browser, making it an ideal partner with any server technology.

So, what is it?

  • Modules
  • Dependency Injection
  • Directives
  • Scopes
  • Controllers
  • Services (Factories)
  • Template

how it's working?

TWO-Way Data binding

Angular 2

Key Features

LEts The carnage Begins!

PLATFORM

AngularJS

Angular 2

PLATFORM

(function(app) {
    var ng = require('@angular/core');
    var router = require('@angular/router');
    var heroService = require('./hero.service');
    var DashboardComponent = (function() {
        function DashboardComponent(heroService, router) {
            this.heroService = heroService;
            this.router = router;
        }
        DashboardComponent.prototype.ngOnInit = function() {
            var _this = this;
            this.heroService.getHeroes()
                .then(function(heroes) {
                    return _this.heroes = heroes.slice(1, 5);
                });
        };
        DashboardComponent.prototype.gotoDetail = function(hero) {
            var link = ['/detail', hero.id];
            this.router.navigate(link);
        };
        DashboardComponent = __decorate([
            ng.core.Component({
                selector: 'my-dashboard',
                templateUrl: 'app/dashboard.component.html',
                styleUrls: ['app/dashboard.component.css']
            }),
            __metadata('design:paramtypes', [heroService.default, router.Router])
        ], DashboardComponent);
        return DashboardComponent;
    }());
    exports.DashboardComponent = DashboardComponent;
})(window.app || (window.app = {}));
import { Component, OnInit } from '@angular/core';
import { Router }            from '@angular/router';

import Hero from './hero';
import HeroSerive from './hero.service';

@Component({
  selector: 'my-dashboard',
  templateUrl: 'app/dashboard.component.html',
  styleUrls: ['app/dashboard.component.css']
})
export class DashboardComponent implements OnInit {
  heroes: Hero[];

  constructor(
    private heroService: HeroSerive,
    private router: Router
  ) { }

  ngOnInit(): void {
    this.heroService.getHeroes()
      .then(heroes => this.heroes = heroes.slice(1, 5));
  }

  gotoDetail(hero: Hero) {
    let link = ['/detail', hero.id];
    this.router.navigate(link);
  }
}

MODularity

AngularJS

Angular 2

  • ng (angular core module)
  • ngAnimate ngCookies ngAria ngRoute
  • ngSanitize etc...

@angular/common

@angular/common/testing

@angular/core

@angular/forms

@angular/http

@angular/router

@angular/platform-browser

@angular/platform-browser-dynamic

@angular/platform-server

@angular/upgrade

@angular/platform-webworker

MODularity

  • ES6 import export
  • Lazy load

Need to do some magic...

DIRectives

var myModule = angular.module(...);

myModule.directive('directiveName', function factory(injectables) {
  var directiveDefinitionObject = {
    priority: 0,
    template: '', // or function
    // or
    // templateUrl: '', // or function
    transclude: false,
    restrict: 'A', // E, C, M, AE, CM, etc
    templateNamespace: 'html',
    scope: false,
    controller: function($scope) { ... },
    controllerAs: '',
    bindToController: false,
    require: 'siblingDirectiveName', 
    multiElement: false,
    compile: function () {}
    // or
    // link: function() {}
    
  };
  return directiveDefinitionObject;
});
import { Directive, Input } from '@angular/core';
import { TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({ selector: '[myUnless]' })
export class UnlessDirective {
  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef
    ) { }
  @Input() set myUnless(condition: boolean) {
    if (!condition) {
      this.viewContainer.createEmbeddedView(this.templateRef);
    } else {
      this.viewContainer.clear();
    }
  }
}

CONTROLLERS

AngularJS

Angular 2

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

myApp.controller('SpicyController', ['$scope', function($scope) {
    $scope.customSpice = 'wasabi';
    $scope.spice = 'very';

    $scope.spicy = function(spice) {
        $scope.spice = spice;
    };
}]);
import { Component, Input, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';

import Hero from './hero';
import HeroService from './hero.service';

@Component({
  selector: 'my-hero-detail',
  templateUrl: 'app/hero-detail.component.html',
  styleUrls: ['app/hero-detail.component.css']
})
export class HeroDetailComponent implements OnInit{
  hero: Hero;

  constructor(
    private heroService: HeroService,
    private route: ActivatedRoute
  ) {}

  ngOnInit(): void {
    this.route.params.forEach((params: Params) => {
      let id = + params['id'];
      this.heroService.getHero(id)
        .then(hero => this.hero = hero);
    });
  }

  goBack(): void {
    window.history.back();
  }

  save(): void {
    this.heroService.update(this.hero)
      .then(this.goBack);
  }
}

DI

AngularJS

Angular 2

// inferred (only works if code not minified/obfuscated)
$injector.invoke(function(serviceA){});

// annotated
function explicit(serviceA) {};
explicit.$inject = ['serviceA'];
$injector.invoke(explicit);

// inline
$injector.invoke(['serviceA', function(serviceA){}]);
// @Injectable()
// class MyService() {}

// providers: [MyService, { provide: ... }]

// constructor(myService: MyService, ...) { ... }

// { provide: MyService, useClass: MyMockService }

// car: Car = this.injector.get(Car);

import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';

import 'rxjs/add/operator/toPromise';

import Hero from './hero';

@Injectable()
export default class HeroService {
  private heroesUrl = 'app/heroes';
  private headers = new Headers({'Content-Type': 'application/json'});

  constructor(private http: Http) {

  }

  //Service logic goes here
}

SERVICEs

AngularJS

Angular 2

var myModule = angular.module('myModule', []);
myModule.factory('serviceId', function() {
  var shinyNewServiceInstance;
  // factory function body that constructs shinyNewServiceInstance
  return shinyNewServiceInstance;
});

app.service('hexafy', function() {
    this.myFunc = function (x) {
        return x.toString(16);
    }
});
import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';

import 'rxjs/add/operator/toPromise';

import Hero from './hero';

@Injectable()
export default class HeroService {
  private heroesUrl = 'app/heroes';
  private headers = new Headers({'Content-Type': 'application/json'});

  constructor(private http: Http) {

  }

  getHeroes(): Promise<Hero[]> {
    return this.http.get(this.heroesUrl)
      .toPromise()
      .then(response => response.json().data as Hero[])
      .catch(this.handleError);
  }
  getHeroesSlowly(): Promise<Hero[]> {
    return new Promise<Hero[]>(resolve => setTimeout(resolve, 2000)).then(() => this.getHeroes());
  }
  getHero(id: number): Promise<Hero> {
    return this.getHeroes().then(heroes => heroes.find(hero => hero.id === id));
  }
  update(hero: Hero): Promise<Hero> {
    const url = `${this.heroesUrl}/${hero.id}`;
    return this.http.put(url, JSON.stringify(hero), {headers: this.headers})
      .toPromise()
      .then(() => hero)
      .catch(this.handleError);
  }
  create(heroName: string): Promise<Hero> {
    const url = `${this.heroesUrl}`;
    return this.getHeroes()
      .then(heroes => {
        var hero = new Hero(heroes.length, heroName);
        return this.http.post(url, JSON.stringify(hero), {headers: this.headers})
          .toPromise()
          .then(() => hero)
          .catch(this.handleError);
      });
  }
  delete(id: number): Promise<void> {
    let url = `${this.heroesUrl}/${id}`;
    return this.http.delete(url, {headers: this.headers})
      .toPromise()
      .then(() => null)
      .catch(this.handleError);
  }

  private handleError(error: any) {
    console.error('An error ocurred', error);
    return Promise.reject(error.message || error);
  }
}

ASYNC

Only Promises are available by default

TEMPLATE SYNTAX

<input [value]="firstName">
<div [attr.role]="myAriaRole">
<div [class.extra-sparkle]="isDelightful">
<div [style.width.px]="mySize">
<button (click)="readRainbow($event)">
<div title="Hello {{ponyName}}">
<p>Hello {{ponyName}}</p>
<my-cmp [(title)]="name"> 
<video #movieplayer ...>
  <button (click)="movieplayer.play()">
</video>
<p *myUnless="myExpression">...</p>
<p>Card No.: {{cardNumber | myCardNumberFormatter}}</p>
p>Employer: {{employer?.companyName}}</p>
<svg:rect x="0" y="0" width="100" height="100"/>
<section *ngIf="showSection">
<li *ngFor="let item of list">
<html ng-app>
 <!-- Body tag augmented with ngController directive  -->
 <body ng-controller="MyController">
   <input ng-model="foo" value="bar">
   <!-- Button tag with ng-click directive, and
          string expression 'buttonText'
          wrapped in "{{ }}" markup -->
   <button ng-click="changeFoo()">{{buttonText | someFilter : orderBy }}</button>
   <script src="angular.js">
 </body>
</html>

DATA Binding

ng-bind, ng-model, {{}}, events <--> scope, controller

<input [(ngModel)]="userName">

@Input() myProperty;

@Output() myEvent = new EventEmitter();

 

DATA Binding

Any questions?

Thank for your attention!

Made with Slides.com