CodeSchool AcceleratingThroughAngular2
CodeSchool AcceleratingThroughAngular2
What Is Angular?
Released in 2011.
Back-end Server
In the Challenges
n
e
e
w
t
e
b
s
e
g
n
e
l
l
a
h
c
f
o
s
t
o
l
h
t
Wi
You dont
need any p
rior experie
nce with A
ngular 1
(optional)
JavaScript: ES2015
ES2015: The Shape of JavaScript to Come
Transpile
main.js
Transpiling Locations
Our browsers dont know how to read TypeScript out of the box, so we have two options
when it comes to changing our TypeScript code into JavaScript.
want to do in production.
HTML
<!DOCTYPE html>
<html>
<head>
<!-- All the Angular 2 libraries needed -->
</head>
</html>
HTML
<!DOCTYPE html>
<html>
<head>
<!-- All the Angular 2 libraries needed -->
</head>
<body>
<my-app>Loading App ...</my-app>
</body>
</html>
HTML
<!DOCTYPE html>
<html>
<head>
<!-- All the Angular 2 libraries needed -->
<script>
...
System.import('app')
.catch(function(err){ console.error(err); });
</script>
</head>
<body>
<my-app>Loading App ...</my-app>
</body>
</html>
TypeScript
import
bootstrap
TypeScript
A decorator
The decorator turns our plain old JavaScript class into a component.
TypeScript
@Component
index.html
<body>
<my-app>Loading App ...</my-app>
</body>
The CSS selector for the HTML element where we want the component to load.
template
TypeScript
index.html
<body>
<my-app>Loading App ...</my-app>
</body>
class AppComponent { }
bootstrap(AppComponent)
TypeScript
TypeScript
Loading an Object
What if we have an object we want to print out onto the screen?
app/main.ts
TypeScript
...
@Component({
selector: 'my-app',
template: '<h1>{{title}} </h1>'
})
class AppComponent {
title = 'Ultra Racing';
carPart = {
"id": 1,
"name": "Super Tires",
"description": "These tires are the very best",
"inStock": 5
};
}
bootstrap(AppComponent);
TypeScript
...
@Component({
selector: 'my-app',
template: `<h1>{{title}} </h1>
<h2>{{carPart.name}}<h2>
<p>{{carPart.description}}<p>
<p>{{carPart.inStock}} in Stock<p> `
})
class AppComponent {
title = 'Ultra Racing';
carPart = {
"id": 1,
"name": "Super Tires",
"description": "These tires are the very best",
"inStock": 5
};
}
bootstrap(AppComponent);
Single Quote
Back Tick
Whatd We Learn?
We are coding Angular using TypeScript, a language that transpiles into JavaScript.
We use a custom HTML tag (aka, selector) to show where we want our component to load
inside our HTML.
Our component decorator is what turns our plain TypeScript class into a component.
Level 2
Structural Directives
Section 1
TypeScript
...
@Component({
selector: 'my-app',
template: `<h1>{{title}}</h1>
<h2>{{carPart.name}}<h2>
<p>{{carPart.description}}<p>
<p>{{carPart.inStock}} in Stock<p>
})
class AppComponent {
title = 'Ultra Racing';
carPart = {
"id": 1,
"name": "Super Tires",
"description": "These tires are the very best",
"inStock": 5
};
}
bootstrap(AppComponent);
TypeScript
...
})
class AppComponent {
title = 'Ultra Racing';
carParts = [{
"id": 1,
"name": "Super Tires",
"description": "These tires are the very best",
"inStock": 5
},
{
"id": 2,
"name": "Reinforced Shocks",
"description": "Shocks made from kryptonite",
"inStock": 4
}, { ... }];
}
bootstrap(AppComponent);
TypeScript
...
@Component({
selector: 'my-app',
template: `<h1>{{title}}</h1>
<ul>
<li *ngFor="let carPart of carParts">
<h2>{{carPart.name}}<h2>
<p>{{carPart.description}}<p>
<p>{{carPart.inStock}} in Stock<p>
</li>
</ul>`
})
class AppComponent {
title = 'Ultra Racing';
carParts = [{
"id": 1,
"name": "Super Tires",
"description": "These tires are the very best",
"inStock": 5
}, { ... }, { ... }];
*ngFor
is a structural directive.
carPart
carParts
is a local variable.
is the array to loop through.
TypeScript
...
@Component({
selector: 'my-app',
template: `<h1>{{title}}</h1>
<ul>
<li *ngFor="let carPart of carParts">
<h2>{{carPart.name}}<h2>
<p>{{carPart.description}}<p>
<p>{{carPart.inStock}} in Stock<p>
</li>
</ul>`
})
class AppComponent {
...
TypeScript
...
@Component({
selector: 'my-app',
template: `<h1>{{title}}</h1>
<ul>
<li *ngFor="let carPart of carParts">
<h2>{{carPart.name}}<h2>
<p>{{carPart.description}}<p>
<p *ngIf="carPart.inStock > 0">{{carPart.inStock}} in Stock</p>
<p *ngIf="carPart.inStock === 0">Out of Stock</p>
</li>
</ul>`
If true, display this.
})
class AppComponent {
...
*ngIf
Whatd We Learn?
*ngFor
*ngIf
Level 2
TypeScript
...
@Component({
selector: 'my-app',
template: `<h1>{{title}}</h1>
<ul>
<li *ngFor="let carPart of carParts">
<h2>{{carPart.name | uppercase }}<h2>
<p>{{carPart.description}}<p>
<p *ngIf="carPart.inStock > 0">{{carPart.inStock}} in Stock</p>
<p *ngIf="carPart.inStock === 0">Out of Stock</p>
</li>
</ul>`
})
class AppComponent {
...
TypeScript
TypeScript
...
@Component({
selector: 'my-app',
template: `<h1>{{title}}</h1>
<ul>
<li *ngFor="let carPart of carParts" >
<h2>{{carPart.name | uppercase }}</h2>
<p>{{carPart.description}}</p>
<p>{{carPart.price | currency:'EUR'}}</p>
<p *ngIf="carPart.inStock > 0">{{carPart.inStock}} in Stock</p>
<p *ngIf="carPart.inStock === 0">Out of Stock</p>
<li>
<ul>`
})
class AppComponent {
...
TypeScript
...
@Component({
Notice the colon
selector: 'my-app',
template: `<h1>{{title}}</h1>
between parameters.
<ul>
<li *ngFor="let carPart of carParts" >
<h2>{{carPart.name | uppercase }}</h2>
<p>{{carPart.description}}</p>
<p>{{carPart.price | currency:'EUR':true }}</p>
<p *ngIf="carPart.inStock > 0">{{carPart.inStock}} in Stock</p>
<p *ngIf="carPart.inStock === 0">Out of Stock</p>
<li>
<ul>`
})
class AppComponent {
...
date
Well, lowercase...
Formats dates how you like them.
You can
also crea
te custo
m pipes
!
number
Formats numbers.
decimal
Formats decimals.
replace
slice
json
main.ts
TypeScript
...
@Component({
selector: 'my-app',
template: `<h1>{{title}}</h1>
<ul>
<li *ngFor="let carPart of carParts">
...
TypeScript
...
@Component({
selector: 'my-app',
template: `<h1>{{title}}</h1>
<p>There are {{ totalCarParts() }} total parts in stock.</p>
<ul>
<li *ngFor="let carPart of carParts">
...
TypeScript
...
@Component({
selector: 'my-app',
template: `<h1>{{title}}</h1>
})
class AppComponent {
title = 'Ultra Racing';
carParts = [...];
totalCarParts() {
return 10;
}
}
TypeScript
class AppComponent {
title = 'Ultra Racing';
carParts = [...];
totalCarParts() {
let sum = 0;
ES2015
Whatd We Learn?
index.html
app
main.ts
totalCarParts() {
return this.carParts.reduce(function(prev, current) { return prev + current.inStock; }, 0 );
}
Level 3
main.ts
o
w
t
e
v
a
h
l
l
i
w
e
w
,
s
i
h
t
.
After
e
n
o
f
o
d
a
e
t
s
n
i
s
t
n
e
n
compo
TypeScript
TypeScript
bootstrap(AppComponent)
app.component.ts
TypeScript
TypeScript
app.component.ts
TypeScript
TypeScript
TypeScript
TypeScript
car-parts.component.ts
@Component({
selector: 'my-app',
template: `<h1>{{title}}</h1> `
})
export class AppComponent {
title = 'Ultra Racing';
}
@Component({
selector: 'car-parts',
template: `
<car-parts>
TypeScript
t
n
e
n
o
p
m
o
c
w
e
n
r
u
o
g
in
d
lu
Inc
e
h
t
n
e
e
w
t
e
b
g
in
h
t
o
N
car-parts tag
TypeScript
Now it works!
This isnt
what we
r
e
building
well k
eep it eve
n simpler
.
Whatd We Learn?
Our main.ts is where we import our rst component and bootstrap it.
We use the directives metadata to list the directives our component uses.
index.html
app
main.ts
app.component.ts
car-parts.component.ts
Level 3
TypeScript
TypeScript
})
export class CarPartsComponent {
,
d
e
p
o
c
s
e
r
a
s
e
Angular 2 adds this custom attribute to scope
i
t
r
e
p
o
r
p
e
k
i
l
a
!
d
the CSS to only this component.
o
n
o
t
Ki
d
e
p
o
c
s
s
i
S
S
C
the
Mind Blown
Lets split out our HTML and CSS into different les.
car-parts.component.html
Where our HTML for the component lives.
car-parts.component.css
Where our CSS for the component lives.
t
u
b
,
u
o
y
t
u
o
b
a
w
o
n
k
t
I don
.
e
m
o
t
y
s
s
e
m
s
l
e
e
f
s
i
th
TypeScript
TypeScript
car-parts.component.html
HTML
car-parts.component.css
.description {
color: #444;
font-size: small;
}
.price {
font-weight: bold;
}
Once we create new les for our HTML and CSS, we can reference
them inside our component metadata.
d
e
p
o
c
s
s
t
e
g
l
l
i
t
s
S
S
C
The
.
e
r
o
f
e
b
e
k
i
l
t
s
u
j
CSS
Whatd We Learn?
HTML and CSS can get split out into their own les.
index.html
app
main.ts
app.component.ts
car-parts.component.ts
car-parts.component.html
car-parts.component.css
Level 3
TypeScript
e
w
e
r
u
s
n
e
TypeScript
car-part.ts
export class CarPart {
id: number;
name: string;
description: string;
inStock: number;
price: number;
}/
TypeScript
TypeScript
TypeScript
TypeScript
...
carParts: CarPart[] = [{
"id": 1,
"name": "Super Tires",
"description": "These tires are the very best",
"inStock": 5,
"price": 4.99
}, { ... }, { ... }];
car-parts.component.html
car-part.ts
export class CarPart {
id: number;
name: string;
description: string;
inStock: number;
price: number;
}/
HTML
TypeScript
TypeScript
mocks.ts
TypeScript
TypeScript
mocks.ts
TypeScript
ngOnInit is invoked after the component is constructed and is the best place to
initialize property values.
app/car-parts.component.ts
import { Component } from '@angular/core';
import { CarPart } from './car-part';
import { CARPARTS } from './mocks';
car-part.ts
The data model
mocks.ts
The fake data
car-parts.component.html
car-parts.component.css
@Component({
selector: 'car-parts',
templateUrl: 'app/car-parts.component.html',
styleUrls:['app/car-parts.component.css']
})
export class CarPartsComponent {
carParts: CarPart[] ;
...
Whatd We Learn?
TypeScript helps us specify class property types that help our compiler ensure were
writing good code.
Its a good practice to keep your mock data separate from your model and your
components, in its own le.
Level 4
style.css
s
e
g
a
m
i
e
h
t
g
Well be addin
.
l
e
v
e
l
s
i
h
t
r
e
t
a
l
y
t
i
t
n
a
u
q
d
an
index.html
css
style.css
style.css
app
app.component.ts
car-parts.component.ts
car-parts.component.html
car-parts.component.css
index.html
css
style.css
style.css
app
app.component.ts
car-parts.component.ts
car-parts.component.html
car-parts.component.css
e
r
u
g
t
e
l
t
u
Much better, b
.
n
i
s
e
g
a
m
i
g
n
i
out how to br
HTML to JavaScript
JavaScript to HTML
In our application thus far, weve been sending all sorts of data from our components
into our HTML using interpolation.
car-parts.component.html
TypeScript
TypeScript
images
tire.jpg
shocks.jpg
seat.jpg
mocks.ts
TypeScript
TypeScript
TypeScript
CSS
...
.featured {
background: #57595D;
-webkit-border-image: -webkit-linear-gradient(right, #818fd8 0%, #cbb4e2 50%, #a6f2f5 100%);
-o-border-image: linear-gradient(to left, #818fd8 0%, #cbb4e2 50%, #a6f2f5 100%);
border-image: linear-gradient(to left, #818fd8 0%, #cbb4e2 50%, #a6f2f5 100%);
border-image-slice: 1;
}
TypeScript
mocks.ts
TypeScript
TypeScript
<ul>
<li class="card" *ngFor="let carPart of carParts" [class.featured]="carPart.featured" >
<div class="panel-body">
...
</div>
</li>
</ul>
<div [class.name]="property">
Whatd We Learn?
Property binding allows us to bind component properties to any DOM element properties.
Any update to the component property value will update the DOM property, but not vice
versa thats why its one-way binding.
Class binding allows us to specify a CSS class to add to a DOM element if a component
property is true.
Level 4
Event Binding
Section 2
JavaScript to HTML
HTML to JavaScript
Event Binding
TypeScript
mocks.ts
TypeScript
TypeScript
...
export class CarPartsComponent {
...
upQuantity() {
alert("You Called upQuantity");
}
...
To capture an event from our template, we wrap the name of the event we want to
listen to in parentheses and specify the method to call.
car-parts.component.html
HTML
...
<td class="price">{{carPart.price | currency:'EUR':true }}</td>
<td>
<div class="select-quantity">
<button class="increase" (click)="upQuantity()">+</button>
...
HTML
TypeScript
Limited Incrementing
We shouldnt be able to add more quantity than we have in stock.
car-parts.component.html
HTML
car-parts.component.ts
TypeScript
HTML
car-parts.component.ts
TypeScript
getCoord(event) {
console.log(event.clientX + ", " + event.clientY);
}
Whatd We Learn?
Event binding allows us to listen to any DOM event and call a component method when
its triggered.
To listen to any event, we need to remove the on in front of the word, wrap it in
parentheses, and specify a component method to call.
If we need to access the event object, we can pass it in to our component method with
$event.
Level 4
Two-way Binding
Section 3
Both Ways
HTML
HTML
This gives us our quantity value in our input box, but only in one
direction: from our component property to our input value.
HTML
Using ngModel
ngModel allows us to have one command to express two-way data binding.
car-parts.component.html
HTML
[()]
This syntax is sometimes called banana in a box can you see why?
Whatd We Learn?
The [(ngModel)] syntax allows us to specify a component property that will use
two-way binding.
Two-way binding means that if the component property is modied inside the
component (JavaScript) or inside our web page (HTML), it will stay in sync.
Level 5
Services
Section 1
TypeScript
mocks.ts
TypeScript
ngOnInit() {
this.carParts = CARPARTS;
}.
...
We are loading our CarParts by importing our mock le, but this isnt the best
solution for working with data.
car-parts.component.ts
TypeScript
Introducing Services
Services are used to organize and share code across your app, and theyre usually where we
create our data access methods.
car-parts.component.ts
First, lets create the simplest service, and then well learn something
called dependency injection to make it even more powerful.
TypeScript
car-parts.component.ts
TypeScript
Dependency Injector
Could I have
RacingDataService?
racing-data.service.ts
car-parts.component.ts
Classes we depend on
Re-injecting Dependencies
If the injector already created a service, we can have it resend the same service.
RacingDataService?
car-cart.component.ts
Dependency Injector
car-parts.component.ts
racing-data.service.ts
These are the providers I have they tell me what I can create and send.
Dependency Injector
racing-data.service.ts
another.service.ts
api.service.ts
There are three steps to make this all work with RacingDataService:
1. Add the injectable decorator to RacingDataService.
2. Let our injector know about our service by naming it as a provider.
3. Inject the dependency into our car-parts.component.ts.
racing-data.service.ts
TypeScript
TypeScript
...
import { RacingDataService } from './racing-data.service';
@Component({
selector: 'my-app',
template: `...`,
directives: [CarPartsComponent],
providers: [RacingDataService]
})
TypeScript
...
import { RacingDataService } from './racing-data.service';
@Component({ ... })
export class CarPartsComponent {
carParts: CarPart[];
We dont ne
ed to add R
acingData
Service
as a provide
r since its
a subcompo
nent.
TypeScript
...
import { RacingDataService } from './racing-data.service';
@Component({ ... })
export class CarPartsComponent {
carParts: CarPart[];
constructor(private racingDataService: RacingDataService) { }
ngOnInit() {
this.carParts = this.racingDataService.getCarParts();
}
}
Whatd We Learn?
Services are used to organize and share code across your app, and theyre usually where
you create your data access methods.
We use dependency injection to create and send services to the classes that need them.
We give our dependency injector providers so that it knows what classes it can create and
send for us.
Level 5
Adding Http
Section 2
Internet
Server
car-parts.json
app.component.ts
4. Inject the http dependency into our service and make the http get request.
racing-data.service.ts
car-parts.component.ts
JSON
"data": [
{
make it feel a little
"id": 1,
"name": "Super Tires",
"description": "These tires are the very best",
"inStock": 5,
"price": 4.99,
"image": "/images/tire.jpg",
"featured": false,
"quantity": 0
},
{ ... },
{ ... }
]
}
more realistic.
TypeScript
...
import { RacingDataService } from './racing-data.service';
import { HTTP_PROVIDERS } from '@angular/http';
@Component({
selector: 'my-app',
template: `...`
directives: [CarPartsComponent],
providers: [RacingDataService, HTTP_PROVIDERS]
})
Now well be able to inject the HTTP library when we need it.
racing-data.service.ts
import
import
import
import
@Injectable()
export class RacingDataService {
constructor(private http: Http) { }
e
c
i
v
r
e
s
r
u
o
e
s
u
a
c
e
b
s
i
h
We can do t
e
l
b
a
t
c
e
j
n
i
s
class i
getCarParts() {
return this.http.get('app/car-parts.json')
.map(response => <CarPart[]>response.json().data);
}
}
<CarPart[]>
response.json()
.data);
TypeScript
...
export class CarPartsComponent {
constructor(private racingDataService: RacingDataService) { }
ngOnInit() {
this.racingDataService.getCarParts()
.subscribe(carParts => this.carParts = carParts);
}
...
When carParts arrive on our data stream, set it equal to our local carParts array.
TypeScript
totalCarParts() {
let sum = 0;
TypeScript
Whatd We Learn?
Angular apps usually load data using service classes after the Angular app is initialized
and running.
Our http calls return an observable, not a promise, which behaves more like an array.