Angular 2: What To Expect

by Jeremy Mason


Download the slides

https://github.com/jeremyalan/Angular2-WhatToExpect

Contact me

jeremyalan@gmail.com
Twitter @jeremyalan

Quick Poll

Audience

I'm assuming you're either...
  • New to web development
  • New to Angular
  • Currently using Angular 1.x
    Preparing for Angular 2

Why Angular 2?

Why Angular 2?

  • Performance
  • Web Standards

Why Angular 2?

Performance

Mobile First

  • Low horsepower
  • Impatient users
  • Hybrid mobile apps

Why Angular 2?

Performance

$scope.$digest();

  • No dirty checking
  • No $scope watchers
  • Uni-directional data flow
    (no two-way data binding)

Why Angular 2?

Web Standards

EcmaScript v6 (ES6)

  • Module Imports
    angular.module(...)
  • Class + Annotations
    <module>.controller(...)

Why Angular 2?

Web Standards

Web Components

  • Template syntax
    • Lazy-binding attributes (e.g. ng-src, ng-href)
    • Custom event handlers (e.g. ng-click, ng-change)
  • Use "native" web components
    • Avoid Angular wrappers on existing components

Angular 2

Is All About Components!

(Bye-Bye MVW)

Components

noun; a part or element of a larger whole

Components

API

PropertiesThe state of the component
.disabled
.value
Methods
The behavior of the component
.click()
.focus()
Events
Notifies listeners of state changes
.on('click', ...)
.on('change', ...)

Components

Structure

Visual

  • HTML
  • Custom Element
  • Attributes
  • Template

Logical

  • JavaScript
  • Controller
  • Services
  • Nested Components

Template Syntax

Custom Elements

<media></media>

Template Syntax

Custom Attributes

String literals
<media title="Hello {{ user.Name }}"></media>
supports interpolation via {{ }}

Template Syntax

Custom Attributes

Property Binding
<media [url]="media.url"></media>
<media bind-url="media.url"></media>
A few notes...
  • No more    '@'   '='   '&'
  • No need for ng-src, ng-href
  • One-way binding only!

Template Syntax

Custom Events

Event Binding
<media (play)="onPlay($event)"></media>
<media on-play="onPlay($event)"></media>
A few notes...
  • Use $event for custom data
  • No need for ng-click, ng-change

Template Syntax

Pipes

Usage example
<media title="{{ media.title | uppercase }}"></media>
  • Similar to "filters" in Angular 1.x

Template Syntax

Pipes

export class Pipe {

    // True if the value can be transformed.
    // False, otherwise.
    supports(obj): boolean;
    
    // Transforms the value.
    transform(obj);
    
    // Cleans up this instance.
    onDestroy();

}

Template Syntax

Ref Bindings

Template
<my-component>
  <label>Your name: <label>
  <input #name />

  <button (click)="sayHello(name.value)">Say Hello</button>
</my-component>
Controller
class MyComponent {
    sayHello(name: string) {
       alert('Hello ' + name + '!');
    }
}

Template Syntax

Templates

  • Declare a snippet of HTML without rendering it
  • Similar to compile/link separation in Angular 1.x
Repeaters
<ul>
  <li *ng-for="#user in users">
    <span>{{ user.Name }}</span>
  </li>
</ul>
(without short-hand syntax)
<template [ng-for] #user [ng-for-of]="users">...</template>

Template Syntax

Templates

  • Declare a snippet of HTML without rendering it
  • Similar to compile/link separation in Angular 1.x
Conditionals
<div *ng-if="isError">
  Login failed, please try again.
</div>
(without short-hand syntax)
<template [ng-if]="isError">...</template>

Template Syntax

Transclusion

isolate $scope + compile + transcludeFn...
(makes sense, right?)

Template Syntax

Transclusion

Usage
<my-component>
  
    <header>
      <!-- Header -->
    </header>
    
    <main>
      <!-- Content -->
    </main>
    
    <footer>
      <!-- Footer -->
    </footer>

</my-component>
Implementation
<div class="container">
  <div class="header">
    <content select="header"></content>
  </div>
    
  <div class="main-content-wrapper">
    <div class="main-content">
      <content select="main"></content>
    </div>
  </div>
    
  <div class="footer">
    <content select="footer"></content>
  </div>
</div>

Controller Syntax

Basics

Things you need to know
  • Class + Module (ES6)
  • Annotations
    (or JavaScript equivalent)
  • Dependency Injection

Controller Syntax

Example

import {Component, View, bootstrap, NgFor} from 'angular2/angular2';
import {ItemStore} from 'services/ItemStore';
 
@Component({
   selector: 'my-app',
   appInjector: [ItemStore]
})
@View({
   templateUrl: 'templates/my-app.html',
   directives: [NgFor]
})
class MyApp {
   _itemStore: ItemStore;
     
   constructor(itemStore: ItemStore) {
      this._itemStore = itemStore;
   }

   add($event, input) {
      this._itemStore.add(input.value);
      input.value = '';
   }
}

bootstrap(MyApp);

Controller Syntax

ES6 Classes

class MyApp {
   constructor() {

   }

   add($event, input) {

   }
}

Controller Syntax

ES6 Modules

import {bootstrap} from 'angular2/angular2';
 
class MyApp {
   constructor() {
   
   }

   add($event, input) {

   }
}

bootstrap(MyApp);

Controller Syntax

Annotations

import {Component, View, bootstrap, NgFor} from 'angular2/angular2';
import {ItemStore} from 'services/ItemStore';

@Component({
   selector: 'my-app'
   appInjector: [ItemStore]
})
@View({
   templateUrl: 'templates/my-app.html',
   directives: [NgFor]
})
class MyApp {
   constructor(itemStore: ItemStore) {

   }

   add($event, input) {

   }
}

bootstrap(MyApp);

Controller Syntax

Annotations

Decorators
  • Proposal for ES7
  • Supported in TypeScript v1.5
  • Syntax for extending classes, methods, and parameters
    @Class
    class MyClass {
        
        @Method
        myMethod(@Param myParam) {
            ...
        }
    
    }
    
Annotations
  • Specific type of decorator
  • Attach metadata to types
    function MyClass() {
        ...
    }
    
    MyClass.annotations = [
        new Foo()
    ]

Controller Syntax

Annotations

3 Basic Annotations
  • @Directive
  • @Component
  • @View

Controller Syntax

Directives

  • selector
    • element-name
    • .class
    • [attribute]
    • [attribute=value]
    • :not(sub_selector)
    • selector1, selector2
  • properties
    • Map properties to HTML
    • Can use pipes
  • events
    • Declare custom events
@Directive({

   selector:
     '<css-selector>',

   properties:
     [
       'propName',
       'propName: attrName',
       'propName: attrName | pipe'
     ],
    
   events:
     [
       '<event-name>'
     ]
     
   // and more ...
})

Controller Syntax

Components

Inherits from Directive
+
  • Creates Shadow DOM
  • Paired with View annotation(s)
  • Assigns Injector
import {MyService} from '...';

@Component({

   // Same as @Directive
   
   appInjector:
       [ MyService ]

   // and more ...
})

Controller Syntax

Views

  • Define the template used to render the component
  • Must declare nested directives
    • Performance
    • Avoid name collisions
import {DirectiveType} from '...';

@View({

   template: 
     '<div></div>',

   templateUrl:
     'path/to/template.html',
    
   directives:
     [ DirectiveType ]

   // and more ...

})

Dependency Injection

Benefits

  • Modularity
    • Single-Responsibility Principle
    • Composition over Inheritance
  • Extensibility
    • Open-Closed Principle
    • Decorator pattern
  • Testability
    • Mock dependencies

Dependency Injection

Injector

The IoC container used by Angular to resolve dependencies
Built on di.js, not specific to Angular
A few things to note...
  • Multiple injectors per application
    • Each injector is associated with a DOM element
  • Injectors are hierarchical
    • Some dependencies resolved by parent/child injectors
    • Replaces $scope inheritance

Dependency Injection

Injector Types

  • Platform Injector
    • Injects browser resources, such as cookies, location, etc.
  • Component Injector
    • Inject custom services (imported via ES6 modules)
  • Element Injector
    • Inject element-specific objects, or other components

Dependency Injection

Services

import {MyService} from '...';

@Component({
   selector: '...',
   appInjector: [ MyService ]
})
class MyComponent {
   constructor(myService: MyService) {
      ...
   }
}

Dependency Injection

Element-Specific Objects

ElementRef
obtain a reference to logical element in the view
ViewContainerRef
control child template instantiation
BindingPropagation
control change detection in a more granular way

Dependency Injection

Directives

Use Annotations to locate directives
<no-decoration>
current element only
@Ancestor
between parent and Shadow DOM root
@Parent
direct parent element only
@Query
a live collection of direct child directives
@QueryDescendants
a live collection of any child directives

Dependency Injection

Directives

app.html
<tabset>
   <tab>
      ...
   </tab>
</tabset>
TabComponent.ts
import {TabSet} from '...';

@Component({
   selector: 'tab'
})
class Tab {
   constructor(@Parent() tabs: TabSet) {
      ...
   }
}

Next Steps

Forms

login.html
<form [control-group]="searchForm">
   <label>Name</label>
   <input type="text" control="name" />
</form>
LoginComponent.ts
import {View} from 'angular2/angular2';
import {FormBuilder, Validators, formDirectives, ControlGroup} from 'angular2/forms';

class LoginComponent {
   searchForm: ControlGroup;
    
   constructor(builder: FormBuilder) {
      this.searchForm = builder.group({
         name: ["", Validators.required]
      });
   }
}

Next Steps

Router

MyController.ts
MyController.$routeConfig = [
  {
    path: '/user',
    components:
      {
        master: 'userList',
        detail: 'user'
      }
  }
];
template.html
<div ng-viewport="master"></div>
<div ng-viewport="detail"></div>

Next Steps

Resources

Thanks!