Angular 2







export class ContactsAppComponent {
  constructor() {}
}
import { Component } from '@angular/core';

@Component({
  selector: 'trm-contacts-app',
  template: `

Hello World!

` }) export class ContactsAppComponent { constructor() {} }

ES5

              (function(app) {
  app.ContactsAppComponent =
    ng.core.Component({
      selector: 'trm-contacts-app',
      template: `

Hello World!

` }) .Class({ constructor: function() {} }); })(window.app || (window.app = {}));

React

              import React from 'react';

export class ContactsAppComponent extends React.Component {
  constructor(props) {}
  render() {
    return 

Hello World

; } }

Core Concepts

{{ }} = interpolation

                

{{ user.name }}

Core Concepts

[ ] = things going in - native props or custom data

                

//jQuery: $('#foo').src = user.avatar

//Angular 1: 

Core Concepts

[ ] = things going in - native props or custom data

                @Component({...})
export class myComponent {

  @Input() user: User;

}

Core Concepts

[ ] = things going in - native props or custom data

<div [ngClass]="{
  'active': isCurrentUser(),
  'is-disabled': user.inactive
}"></div>

Core Concepts

( ) = things coming out - native or custom events

Can access native event with $event



jQuery: $('#foo').on('click', addUser)

Custom event

<my-component (onNewUser)="addUser($event)"></my-component>

Core Concepts

( ) = things coming out - native or custom events

<my-component (onNewUser)="addUser($event)"></my-component>
                @Component({...})
export class myComponent {

  @Output() onNewUser: EventEmitter<any> = new EventEmitter();

  newUser(user) {
    onNewUser.emit(user)
  }
}

Core Concepts

[(ngModel)] = 2 way data binding

Combines input and output

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

Hello, {{name}}!

Core Concepts

Using ngModel we can already create simple forms.

<form>

  <label>Firstname:</label>
  <input [(ngModel)]="contact.firstname">

  <label>Lastname:</label>
  <input [(ngModel)]="contact.lastname">
  ...
</form>

Core Concepts

# = reference to the element

<input #myInput type="text" />

<button (click)="focusInput($event, myInput)"></button>
focusInput(event, input) {
  event.preventDefault();
  input.focus();
}

Core Concepts

# = reference to the element

<input #myInput type="text" />

<button (click)="focusInput($event, myInput)"></button>
focusInput(event, input) {
  event.preventDefault();
  input.focus();
}

Core Concepts

* = directive which manipulates the DOM
(rarely will you create these yourself)

*ngFor: loop over array

<ul>
  <li *ngFor="let hero of heroes">
    {{ hero }}
  </li>
</ul>

Core Concepts

* = directive which manipulates the DOM
(rarely will you create these yourself)

*ngIf: conditional display

<p *ngIf="heroes.length > 3">There are many heroes!</p>

Core Concepts

Define scoped CSS that effects only this component
(css becomes very basic)

@Component({
  selector: 'trm-contacts-app',
  template: `

Hello World

`, styleUrls: ['contacts.component.css'] }) class ContactsAppComponent {...}
h1 {font-size: 24px;}
.active {
  background: yellow;
}

Scoped CSS

Define scoped CSS that effects only this component
(css becomes very basic)

@Component({
  selector: 'trm-contacts-app',
  template: `<h1 class="active">Hello World</h1>`,
  styleUrls: ['contacts.component.css']
})
class ContactsAppComponent {...}
h1 {font-size: 24px;}
.active {
  background: yellow;
}

Examples

@Component({
  selector: 'trm-contacts-app',
  template: 'Hello {{name}}'
})
export class ContactsAppComponent {
  name = 'Angular 2';
}
@Component({
  selector: 'trm-contacts-app',
  template: 'Hello {{name}}'
})
export class ContactsAppComponent {
  name = 'Angular 2';
}

Defining a Contact

interface Contact {
  id: Number;
  name: string;
  email: string;
  phone: string;
  ...
}
import { Contact } from './models/contact';

@Component(...)
export class ContactsAppComponent {







}
import { Contact } from './models/contact';

@Component(...)
export class ContactsAppComponent {
  contact: Contact = {
    id: 1,
    name: 'Christoph',
    email: 'chris@burdorf.io',
    image: 'path/to/image',
    ...
  }
}
@Component({
  selector: 'trm-contacts-app',
  template: `
    
{{contact.name}}
` }) export class ContactsAppComponent { ... }
@Component({
  selector: 'trm-contacts-app',
  template: `
    <div>
      <img [src]="contact.image">
      <span>
        {{contact.name}}
      </span>
    </div>
  `
})
export class ContactsAppComponent {
  ...
}

Creating a list

export const CONTACTS: Contact[] = [
  { id: 1, firstname: 'Christoph', ...},
  { id: 2, firstname: 'Pascal', ...},
  { id: 3, firstname: 'Julie', ...},
  { id: 4, firstname: 'Igor', ...},
  ...
];
import { CONTACTS } from './data/contact-data';

@Component({
  selector: 'trm-contacts-app',
  template: `
    
` }) export class ContactsAppComponent { contacts: Contact[] = CONTACTS; }
import { CONTACTS } from './data/contact-data';

@Component({
  selector: 'trm-contacts-app',
  template: `
    <ul>
      <li>
        <!-- each contact goes here -->
      </li>
    </ul>
  `
})
export class ContactsAppComponent {
  contacts: Contact[] = CONTACTS;
}
@Component({
  selector: 'trm-contacts-app',
  template: `
    <ul>
      <li>

        <!-- each contact goes here -->


      </li>
    </ul>
  `
})
export class ContactsAppComponent {
  ...
}
@Component({
  selector: 'trm-contacts-app',
  template: `
    <ul>
      <li *ngFor="let contact of contacts">
        <img [src]="contact.image">
        <span>
          {{contact.name}}
        </span>
      </li>
    </ul>
  `
})
export class ContactsAppComponent {
  ...
}

Services

We can create services in Angular using classes.

import { Injectable } from '@angular/core';

@Injectable()
export class ContactsService {

  private contacts: Contact[] = CONTACTS;

  getContacts() {
    return this.contacts;
  }
}

Injecting Dependencies

Dependencies can be injected using TypeScript type annotations.

@Component(...)
export class ContactsAppComponent {

  contacts: Contact[];

  constructor(contactsService: ContactsService) {
    this.contacts = contactsService.getContacts();
  }
}

Injecting Dependencies

Dependencies can be injected using TypeScript type annotations.

@Component(...)
export class ContactsAppComponent {

  contacts: Contact[];

  constructor(contactsService: ContactsService) {
    this.contacts = contactsService.getContacts();
  }
}

Lifecycle Hooks

Directives and Components have lifecycle hooks. Some of them are:

  • ngOnInit - Initializes directive
  • ngOnChanges - Respond after Angular sets data-bound property
  • ngDoCheck - Custom change detection
  • ngOnDestroy - Cleanup before Angular destroys directive

OnInit Lifecycle

We use ngOnInit to do initialization work in the component.

import { OnInit } from '@angular/core';
...
export class ContactsAppComponent implements OnInit {

  contacts: Contact[];

  constructor(private contactsService: ContactsService) {}

  ngOnInit() {
    this.contacts = this.contactsService.getContacts();
  }
}

OnInit Lifecycle

We use ngOnInit to do initialization work in the component.

import { OnInit } from '@angular/core';
...
export class ContactsAppComponent implements OnInit {

  contacts: Contact[];

  constructor(private contactsService: ContactsService) {}

  ngOnInit() {
    this.contacts = this.contactsService.getContacts();
  }
}

Fetching Data

Http in Angular 2

Angular 2 introduces a completely redesigned Http layer based on Observables.

  • Event-driven stream of notifications
  • Enables functional programming structures
  • Allows to transform to promises if needed

Http Service

Http is an injectable class with methods to perform http requests.

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

@Injectable()
class ContactsService {
  constructor(private http: Http) {

  }
}

Http Service

Http is an injectable class with methods to perform http requests.

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

@Injectable()
class ContactsService {
  constructor(private http: Http) {

  }
}

Http Service

Http is an injectable class with methods to perform http requests.

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

@Injectable()
class ContactsService {
  constructor(private http: Http) {

  }
}

Http and Observables

Http returns an Observable which will emit a single response it's received.

class ContactsService {
  ...
  getContacts() {
    return this.http.get('http://myapi.com/contacts')
      .map((res) => { return res.json(); })
      .map((data) => { return data.items; });
  }
}

Http and Observables

Http returns an Observable which will emit a single response it's received.

class ContactsService {
  ...
  getContacts() {
    return this.http.get('http://myapi.com/contacts')
      .map((res) => { return res.json(); })
      .map((data) => { return data.items; });
  }
}

Http and Observables

Http returns an Observable which will emit a single response it's received.

class ContactsService {
  ...
  getContacts() {
    return this.http.get('http://myapi.com/contacts')
      .map(res => res.json())
      .map(data => data.items);
  }
}

Subscribing to Http

We can subscribe to Observables using .subscribe()

@Component(...)
class ContactsListComponent {

  constructor(contactsService: ContactsService) {
    contactsService.getContacts()
      .subscribe(contacts => this.contacts = contacts);
  }

}

Subscribing to Http

We can subscribe to Observables using .subscribe()

@Component(...)
class ContactsListComponent {

  constructor(contactsService: ContactsService) {
    contactsService.getContacts()
      .subscribe(contacts => this.contacts = contacts);
  }

}

Pipes

A pipe takes in data as input and transforms it to a desired output.

@Component({
  selector: 'trm-contacts-detail',
  template: `
    ...
    Birthday:
    {{contact?.dateOfBirth | date}}
  `
})
class ContactsDetailComponent { }

Pipes

A pipe takes in data as input and transforms it to a desired output.

@Component({
  selector: 'trm-contacts-detail',
  template: `
    ...
    <span>Birthday:</span>
    <span>{{contact?.dateOfBirth | date}}</span>
  `
})
class ContactsDetailComponent { }

Every component is part of an NgModule

import { NgModule } from '@angular/core';



@NgModule({



})
export class ContactsModule {}
import { NgModule } from '@angular/core';

import { ContactsAppComponent } from './contacts.component';

@NgModule({

  declarations: [ContactsAppComponent],
  bootstrap: [ContactsAppComponent]
})
export class ContactsModule {}
import { NgModule } from '@angular/core';

import { ContactsAppComponent } from './contacts.component';

@NgModule({

  declarations: [ContactsAppComponent],
  bootstrap: [ContactsAppComponent]
})
export class ContactsModule {}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ContactsAppComponent } from './contacts.component';

@NgModule({
  imports: [BrowserModule],
  declarations: [ContactsAppComponent],
  bootstrap: [ContactsAppComponent]
})
export class ContactsModule {}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ContactsAppComponent } from './contacts.component';

@NgModule({
  imports: [BrowserModule],
  declarations: [ContactsAppComponent],
  bootstrap: [ContactsAppComponent]
})
export class ContactsModule {}
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Contacts</title>
  </head>
  <body>



    <script src="..."></script>
  </body>
</html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Contacts</title>
  </head>
  <body>

    <trm-contacts-app>Loading...</trm-contacts-app>

    <script src="..."></script>
  </body>
</html>

Directive Dependencies

Directives/Components are added to an NgModule's declarations property.



@NgModule({
  imports: [BrowserModule],
  declarations: [ContactsAppComponent],
  bootstrap: [ContactsAppComponent]
})
export class ContactsModule {}

Directive Dependencies

Directives/Components are added to an NgModule's declarations property.

import { ContactsHeaderComponent } from './contacts-header';

@NgModule({
  imports: [BrowserModule],
  declarations: [ContactsAppComponent, ContactsHeaderComponent],
  bootstrap: [ContactsAppComponent]
})
export class ContactsModule {}

Directive Dependencies

Directives/Components are added to an NgModule's declarations property.

import { ContactsHeaderComponent } from './contacts-header';

@NgModule({
  imports: [BrowserModule],
  declarations: [ContactsAppComponent, ContactsHeaderComponent],
  bootstrap: [ContactsAppComponent]
})
export class ContactsModule {}

Directive Dependencies

Directives/Components can then be used in components throughout that module.

@Component({
  selector: 'trm-contacts-app',
  template: `

Hello World!

`, }) export class ContactsAppComponent {}

Directive Dependencies

Directives/Components can then be used in components throughout that module.

@Component({
  selector: 'trm-contacts-app',
  template: '<trm-contacts-header></trm-contacts-header>'
})
export class ContactsAppComponent {}

Stuff I didn't cover

  • Router: map urls to components
  • Forms: Validation, etc
  • RxJS: Observable Streams library, how Angular communicates
  • ngrx: RxJS powered state management inspired by Redux
  • Change Detection Options: Performance increases with immutable data