with
I'm Tom: a software developer with 10 years experience building web and mobile apps.
My professional career includes:
Co-founded startup, built web-based touch-screen apps.
Head of mobile web at award-winning mobile app development agency.
Web-based consultancy, specialising in JavaScript development and training.
Tools of the trade:
Find me everywhere as @fiznool
Course overview:
ES6: a recap
Introduction to Angular 2
Wrap-up
Introduction to TypeScript
Workshop: building an Ionic 2 app
A long overdue, major update to JavaScript.
Ratified last year, major browsers are implementing features now.
Polyfills are available for older browsers that do not yet support ES6 features.
let is the new var, const is a var for one-off assignment.
Both correctly scope to blocks, unlike var.
let a = 'bob';
if (1 < 2) {
let a = 'jim';
console.log(a); // 'jim'
}
console.log(a); // 'bob'
var a = 'bob';
if (1 < 2) {
var a = 'jim';
console.log(a); // 'jim'
}
console.log(a); // 'jim'
Syntactic sugar for strings.
Features: string interpolation, newlines and more.
const str = `I am a string`;
const multiline = `I am a string...
on multiple lines!`
const food = 'pizza';
const like = `I like ${food}`;
Syntactic sugar for OO prototypes.
Features: inheritance, super calls, constructors, instance methods, statics, getters/setters.
class Animal {
speak() {
console.log('I have no voice.');
}
}
class Dog extends Animal {
speak() {
console.log('woof.');
}
}
class Dog extends Animal {
constructor(name) {
super(name);
this.legs = 4;
}
get legs() {
return this._legs;
}
set legs(val) {
this._legs = val;
console.log(`I have ${val} legs`);
}
static family() {
return 'Canis';
}
}
const dog = new Dog('Boris');
Shorthand function with lexical scoping of this
.
class Brewery {
constructor(beers) {
this.beers = beers;
this.beers.forEach(beer => {
this.bottle(beer);
});
}
bottle(beer) {
console.log(`bottling ${beer}...`);
}
}
const bathales = new Brewery([
'Gem', 'Wild Hare', 'Barnsey']);
Replacement for arguments
keyword.
class Brewery {
constructor(...beers) {
this.beers = beers;
this.beers.forEach(beer => {
this.bottle(beer);
});
}
bottle(beer) {
console.log(`bottling ${beer}...`);
}
}
const bathales = new Brewery(
'Gem', 'Wild Hare', 'Barnsey');
A promise represents a value or error that will occur in the future.
const p = new Promise(resolve => {
setTimeout(() => {
resolve('hello');
, 200);
});
p.then(msg => {
console.log(msg);
});
In many cases, they are a better async alternative to callbacks.
If the property name and variable are the same,
objects can now be created using shorthand notation.
const data = 'some data';
const obj = { data };
console.log(obj.data); // 'some data'
Export JavaScript primitives and objects, and import them in other places.
// obj-utils.js
export function assign(target, ...sources) {
return Object.assign(target, ...sources);
}
export const proto = Object.prototype;
// app.js
import { assign } from './obj-utils';
assign(obj1, obj2, obj3);
A superset of JavaScript which adds compile-time type checking.
Compiles down to regular JavaScript.
Adopted as the preferred way to write Angular 2 apps.
let name: string;
let age: number;
let ownsCar: boolean;
let childrenNames: string[];
let favouriteThing: any;
name = 'Bob'; // OK
name = 2; // Compiler error
age = 30; // OK
age = 'Thirty'; // Compiler error
ownsCar = true; // OK
ownsCar = 'no'; // Compiler error
childrenNames = ['Sandy', 'Douglas']; // OK
childrenNames = [21, false, 'Jim']; // Compiler error
favouriteThing = 'pizza'; // OK
favouriteThing = 42; // OK
interface Person {
name: string, // required
age: number, // required
hasCar?: boolean // optional
}
const bob: Person = { // OK
name: 'Bob',
age: 30,
hasCar: true
};
const bobless: Person = { // OK
name: 'Bob',
age: 30
};
const jim = { // Compiler error (no age)
name: 'Jim'
};
function add(a: number, b: number): number {
return a + b;
}
let result: number = add(1, 2); // OK
let result: string = add(1, 2); // Compiler error
let result: number = add(1, '2'); // Compiler error
// Use 'void' if returning nothing.
function print(msg: string): void {
console.log(msg);
}
// Or, omit the return type altogether.
function print(msg: string) {
console.log(msg);
}
class Greeter {
// property
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return `Hello, ${this.greeting}`;
}
}
const greeter = new Greeter('world');
greeter.greet();
class Animal {
private name: string;
constructor(name: string) {
this.name = name;
}
}
const lion = new Animal('Simba');
lion.name; // Compiler error
Private properties & methods prevent access from outside the class:
class Animal {
constructor(public name: string) {}
}
const lion = new Animal('Simba');
lion.name; // 'Simba'
Parameter properties are a shorthand if you are setting a property from a constructor:
class Animal<T> {
constructor(public name: T) {}
}
const lion = new Animal<string>('Simba');
lion.name; // 'Simba'
Define the type at runtime.
interface Response {
status: number,
data: any
}
function get(url: string): Promise<Response> {
return new Promise((resolve, reject) => {
$.ajax(url, {
success: data => resolve({ status: 200, data }),
error: (jqXHR, err) => reject({ status: 500, data: err })
});
});
}
Often used for promises:
function Sealed() {
return function(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
};
}
@Sealed()
class Animal {
constructor(public name: string) {}
}
const dog = new Animal('Benji');
// dog will now be sealed
Modify behaviour of classes.
Angular 2 is a major upgrade to 1.x.
A complete rewrite; it's so different you should treat it as a new framework.
Focus on performance, speed and interop across desktop and mobile.
Advocates Component-based architecture
for authoring applications.
In Angular 2, everything you see on screen is rendered by a Component.
<nav></nav>
<footer></footer>
<directory></directory>
<menu> </menu>
import { Component } from '@angular/core';
@Component({
selector: 'lion',
template: '<p>I am a Lion. Roar!</p>
})
export class LionComponent {}
Use <lion>
custom element to render:
<lion></lion>
// lion.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'lion',
templateUrl: 'lion.component.html'
})
export class LionComponent {}
Best practice: move template to separate file with templateUrl
<!-- lion.component.html -->
<p>I am a lion. Roar!</p>
// lion.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'lion',
templateUrl: 'lion.component.html'
})
export class LionComponent {
status = 'fierce';
}
Interpolate variables with {{ }}
<!-- lion.component.html -->
<p>I am a lion, I'm very {{ status }}.</p>
// lion.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'lion',
templateUrl: 'lion.component.html'
})
export class LionComponent {
status = 'fierce';
shouldShow = true;
}
Evaluate variables with [ ]
<!-- lion.component.html -->
<p [hidden]="shouldShow">I am a lion, I'm very {{ status }}.</p>
import { Component } from '@angular/core';
@Component({
selector: 'lion',
templateUrl: 'lion.component.html'
})
export class LionComponent {
status = 'fierce';
speak() {
console.log('roar!');
}
}
Bind events with ( )
<!-- lion.component.html -->
<p (click)="speak()">I am a lion, I'm very {{ status }}.</p>
import { Component } from '@angular/core';
@Component({
selector: 'lion',
templateUrl: 'lion.component.html'
})
export class LionComponent {
status = 'fierce';
}
Guard against undefined properties with
?
<!-- lion.component.html -->
<p>I am a lion, see me {{ actions?.speak }}.</p>
Note: this is different to Angular 1.x, which will
automatically catch undefined properties.
import { Component } from '@angular/core';
@Component({
selector: 'lion',
templateUrl: 'lion.component.html'
})
export class LionComponent {
status = 'fierce';
shouldShow = false;
}
Conditionally render with
*ngIf
<!-- lion.component.html -->
<p *ngIf="shouldShow">I am a lion, and I'm {{ status }}.</p>
Note: this is analogous to ng-if from Angular 1.x
import { Component } from '@angular/core';
@Component({
selector: 'lion',
templateUrl: 'lion.component.html'
})
export class LionComponent {
traits = ['fierce', 'brave', 'powerful'];
}
Repeat with *ngFor
<!-- lion.component.html -->
<p>I am a lion, and I am:</p>
<ul><li *ngFor="let t of traits">{{ t }}</li></ul>
Note: this is analogous to ng-repeat from Angular 1.x
import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
@Component({
selector: 'lion',
templateUrl: 'lion.component.html'
})
export class LionComponent {
constructor(public fb: FormBuilder) {}
createForm() {
this.fb.group(...);
}
}
Inject dependencies in the constructor.
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
@Injectable()
export class LionService {
constructor(public http: Http) {}
getLions() {
this.http.get(...);
}
}
Singleton instances (aka services).
Injectable into components.
<form>
<div class="form-group">
<label for="username">Username</label>
<input type="text" name="username" [(ngModel)]="user.username">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" name="password" [(ngModel)]="user.password">
</div>
</form>
Template-driven: uses ngModel inside component template to bind form elements.
interface User {
username: string, password: string
}
@Component({ ... })
export class UserComponent {
user: User;
}
<form [formGroup]="userForm">
<input type="text" formControlName="username">
<input type="password" formControlName="password">
</form>
Model-driven: uses FormBuilder inside component to bind form elements.
@Component({ ... })
export class UserComponent {
userForm: FormGroup;
constructor(public fb: FormBuilder) {}
createForm() {
this.userForm = this.fb.group({
username: [''],
password: ['']
});
}
Transform data for display.
@Pipe({
name: 'timeago'
})
@Injectable()
export class Timeago {
transform(value) {
return new timeago().format(value);
}
}
@Component({
template: '<p>{{ published | timeago }}</p>'
})
export class FeedComponent {
published = Date.now();
}
Combine components, providers and pipes
into logical units of functionality.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Hybrid mobile app framework based on Angular.
Build using web technologies.
Compile for iOS, Android and Windows Phone through Cordova.
$ npm install -g ionic cordova
We'll be building a RSS reader.
App will speak to an external API to load articles.
Install dependencies:
$ xcode-select --install
$ npm install -g ios-sim ios-deploy
$ ionic platform add ios
$ ionic emulate ios
$ ionic build ios
xcodeproj
file in the platforms/ios folder. This will open Xcode.Install dependencies:
$ ionic platform add android
$ ionic run android
In the terminal, type
The app will be deployed to the phone, and will automatically open.