Angular 2 is coming!

@timruffles @sidekicksrc

Angular 2 is still in the works. The core concepts are solid, but the API may change

Victor Savkin, 12th Oct.

But...

Google in production

Big goals

Components

Dependecy Injection

Evolution from ng1

Components

Our first component

import { Component } from 'angular2/angular2';

export { HelloComponent };

@Component({
  selector: 'hello-angular',
  template: '<h1>{{ message }}</h1>',
})
class HelloComponent {
  constructor() { 
    this.message = "Hi there";
  }
}

Woah!

Bit by bit

import { Component } from 'angular2/angular2';

export { HelloComponent };

@Component({
  // any CSS selector
  selector: 'hello-angular',
  // ...
})

@Component({
  // ...
  template: '<h1>{{ message }}</h1>',
})

class HelloComponent {
  constructor() { 
    this.message = "Hi there";
  }
}

All together

import { Component } from 'angular2/angular2';

export { HelloComponent };

@Component({
  selector: 'hello-angular',
  template: '<h1>{{ message }}</h1>',
})
class HelloComponent {
  constructor() { 
    this.message = "Hi there";
  }
}

That's an app!

import { HelloComponent } from "./HelloComponent";
import { bootstrap } from "angular2/angular2";

bootstrap(HelloComponent);
<!DOCTYPE html>
<hello-component></hello-component>
<!-- with a production bundle -->
<script src="dist/app.js"></script>

Hierarchy

import { Component } from 'angular2/angular2';
import { HelloComponent } from './HelloComponent';

export { FrontPage };

@Component({
  selector: 'front-page',
  directives: [HelloComponent],
  template: '<hello-angular></hello-angular>',
})
class FrontPage {
}

Explicit

import { Component, FORM_DIRECTIVES, CORE_DIRECTIVES }
 from 'angular2/angular2';

@Component({
  directives: [FORM_DIRECTIVES, CORE_DIRECTIVES],
  // ...
})

New template syntax

Data binding

<!-- like ng 1 - interpolated -->
<div title="Hello {{ person }}">
<!-- whole attribute -->
<div [title]="getMessage()">

Pipes (new name for filters)

<div [title]="getMessage() | toTitle">

Event-handling

<!-- DOM events -->
<form (submit)="create($event)">

Two-way data-binding

<!-- the local ourName property will be two way bound to name
     of our some-editor component -->
<some-editor ([name])="ourName">

Local variables

<video #movieplayer >
  <button (click)="movieplayer.play()">
</video>

Let's have a go

Better DI

First: why DI?

Two benefits

One: testing

Two: multiple implementations

Angular 1

Crufty

module.service("User", calledWithNew);
module.factory("User", usesReturnValue);
module.provider("User", returnsProviderConfig);
module.value("User", User);

Implicit

  • e.g 'where did this service come from?!'
  • file location opaque
module.controller("UserCtrl", function(
  User
  , Login
  , errors
) {
  // unclear where the above came from physically
  // (without conventions)
})

App-wide

  • Can't switch provider for part of an app

Angular 2

Let's define a 'service'

Oh

export { Greeter };

class Greeter {
  message(name) {
    return 'Hello ${name}, 
      Angular 2 is easy';
  }
}

Using a service

Better API

import { Component } from 'angular2/angular2';
import { Greeter } from './greeter';

@Component({
  // setup
  providers: [Greeter],
})
class HelloComponent {
  constructor(greeter: Greeter) { 
    this.message = greeter.message();
  }
}

Hierarchical

import { Greeter } from './greeter';

bootstrap(FrontPage, [Greeter]);
import { Greeter } from './greeter';

@Component({
  // don't be explicit
  providers: [],
})
class HelloComponent {
  constructor(greeter: Greeter) { 
  }
}

Tree

injector tree

Let's have a go

Evolution

1.5

  • new module.component method
  • aiming for Jan

ngUpgrade

  • can run ng 1 and ng 2 in parallel

Learning from 1.x

Routing

Component Router

  • 1.x and 2.x

Structured

component router

Let's have a go

Performance

Pre-compilation

  • reduces load and run cost

Web-workers

  • only UI updates run in main thread
  • does require certain constraints

Mobile

Native Script

Predicability

ng 1 change detection

$scope

Behind the scenes

$apply()

  • library authors: wrap all async
// rought version of ng-click
el.on("click", function(event) {
  $scope.$apply(function() {
    $scope.$eval(userCallback, {
      $event: event,
    });
  });
});

Pretty good, still nasty

ng 2: no $scope

Zones!

@Component({
  selector: 'toggler',
  template: '<button (click)="toggle()">
    {{ msg }}</button>',
})
class TogglerComponent {
  constructor() { 
    this.msg = "Click me";
  }
  toggle() {
    this.msg = "You clicked me!";
    setTimeout(() => { 
      this.msg = "Click me";
    }, 250);
  }
}

How?

Patching

Zones patch all async:

window.setTimeout = function(fn, timeout) {
  originalTimeout(zone.callback(fn), timeout);
}

MOAR!!!

  • RxJS support
  • Immutables via controlling updates
  • ES.next support, non-TypeScript

ng2 summary

Broad goals

  1. Components
  2. Better DI
  3. Evolution: router, animation, tests etc

vs ng1, ng2 apps:

  1. Better isolation of components
  2. More maintainable: ability to swap out services locally
  3. Predictable: immutability, one-way data-flow
  4. Better: powerful routing, animation

Thanks!

@timruffles