Pluralsight - Angular Getting Started
Pluralsight - Angular Getting Started
INTRODUCTION
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | blogs.msmvps.com/deborahk/
Angular Is …
A JavaScript framework
For building client-side applications
Using HTML, CSS and JavaScript
Why Angular?
Application
= Component
+ Component
+ Component …
Services
Component
Class
= + +
Properties
Component Template Metadata
Methods
Angular Modules
Root Feature
Angular Module Angular Module
Component Component
Component Component
Component Component
Component Component
Prerequisites
@deborahkurata
Blog Post
http://blogs.msmvps.com/deborahk/angular-2-getting-started-problem-solver/
Checklist
https://github.com/DeborahK/Angular-GettingStarted
Demo
Introduction to Components
More on Components
Angular Modules
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | blogs.msmvps.com/deborahk/
Module
Overview Selecting a Language
Selecting an Editor
Setting up an Angular Application
About Modules
JavaScript Language Specification
ECMAScript (ES)
ES 3
ES 5
ES 2015 (formerly known as ES 6)
- Must be transpiled
Selecting a Language
Class-based object-orientation
Learning More
TypeScript Playground
http://www.typescriptlang.org/Playground/
Pluralsight Courses
"TypeScript Fundamentals"
"AngularJS with TypeScript"
"Using ES6 with TypeScript"
TypeScript Editors
Visual Studio
WebStorm
Atom
Eclipse
Others
Visual Studio Code
https://code.visualstudio.com/
Learning More
npm
Set up the Angular application
npm
AngularJS TypeScript
Modules Modules
ES 2015 Angular
Modules Modules
ES 2015 Modules
Export Import
product.ts product-list.ts
product.js
Transpile
function Product() {
}
Angular Modules
Component Component
Component Component
Component Component
Modules
index.html
Response
JavaScript
Summary Selecting a Language
Selecting an Editor
Setting up an Angular Application
About Modules
Application Architecture
Welcome
Component
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | blogs.msmvps.com/deborahk/
Module
Overview What Is a Component?
Creating the Component Class
Defining the Metadata with a Decorator
Importing What We Need
Bootstrapping Our App Component
Application Architecture
Welcome
Component
Class
= + +
Properties
Component Template Metadata
Methods
@Component({
selector: 'pm-root',
template: `
<div><h1>{{pageTitle}}</h1> Metadata &
<div>My First Component</div> Template
</div>
`
})
export class AppComponent {
pageTitle: string = 'Acme Product Management'; Class
}
Creating the Component Class
app.component.ts
app.component.ts
class
Class Name
keyword
Property Default
Data Type
Name Value
Methods
Defining the Metadata
app.component.ts
@Component({
selector: 'pm-root',
template: `
<div><h1>{{pageTitle}}</h1>
<div>My First Component</div>
</div>
`
})
export class AppComponent {
pageTitle: string = 'Acme Product Management';
}
Decorator
A function that adds metadata to a class, its members, or its
method arguments.
Prefixed with an @.
Angular provides built-in decorators.
@Component()
Defining the Metadata
app.component.ts
Component
@Component({
decorator
selector: 'pm-root',
template: ` Directive Name
<div><h1>{{pageTitle}}</h1> used in HTML
<div>My First Component</div>
</div>
` View Layout
})
export class AppComponent {
pageTitle: string = 'Acme Product Management'; Binding
}
Importing What We Need
https://www.npmjs.com/~angular
Importing What We Need
app.component.ts
@Component({
selector: 'pm-root',
template: `
<div><h1>{{pageTitle}}</h1>
<div>My First Component</div>
</div>
`
})
export class AppComponent {
pageTitle: string = 'Acme Product Management';
}
Importing What We Need
app.component.ts
import { Component } from '@angular/core'; import keyword
@Component({
selector: 'pm-root',
template: `
<div><h1>{{pageTitle}}</h1>
<div>My First Component</div>
</div>
`
})
export class AppComponent {
pageTitle: string = 'Acme Product Management';
}
Demo
index.html app.component.ts
<body> import { Component } from '@angular/core';
<pm-root></pm-root>
</body> @Component({
selector: 'pm-root',
template: `
<div><h1>{{pageTitle}}</h1>
<div>My First Component</div>
</div>
`
})
export class AppComponent {
pageTitle: string = 'Acme Product Management';
}
BrowserModule
Organization
AppModule Boundaries
Template resolution
environment
AppComponent
Imports
Exports
Declarations
Providers
Bootstrap
Defining the Angular Module
app.module.ts
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 { }
Demo
Bootstrapping Our
App Component
Component Checklist
export keyword
Data in properties
- Appropriate data type
- Appropriate default value
- camelCase with first letter lowercase
Logic in methods
- camelCase with first letter lowercase
Component Checklist: Metadata
Component decorator
- Prefix with @; Suffix with ()
Module path
- Enclose in quotes
- Correct spelling/casing
Something's Wrong! Checklist
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | blogs.msmvps.com/deborahk/
Component
Class
= + +
Properties
Component Template Metadata
Methods
Module
Overview Building a Template
Using a Component as a Directive
Binding with Interpolation
Adding Logic with Directives
Application Architecture
Welcome
Component
@Component({
selector: 'pm-root',
template: `
<div><h1>{{pageTitle}}</h1>
<div>My First Component</div>
</div>
`
})
export class AppComponent {
pageTitle: string = 'Acme Product Management';
}
Defining a Template in a Component
http://getbootstrap.com/
Building the Component
product-list.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'pm-products',
templateUrl: './product-list.component.html'
})
export class ProductListComponent {
pageTitle: string = 'Product List';
}
Using a Component as a Directive
app.component.ts product-list.component.ts
@Component({ @Component({
selector: 'pm-root', selector: 'pm-products',
template: ` templateURL:
<div><h1>{{pageTitle}}</h1> './product-list.component.html'
<div>My First Component</div> })
</div>` export class ProductListComponent { }
})
export class AppComponent { }
Using a Component as a Directive
app.component.ts product-list.component.ts
@Component({ @Component({
selector: 'pm-root', selector: 'pm-products',
template: ` templateURL:
<div><h1>{{pageTitle}}</h1> './product-list.component.html'
<pm-products></pm-products> })
</div>` export class ProductListComponent { }
})
export class AppComponent { }
BrowserModule
AppModule
AppComponent
Imports
Exports
Declarations
Providers
Bootstrap
BrowserModule
AppModule
AppComponent
ProductList -
Component
Imports
Exports
Declarations
Providers
Bootstrap
Binding
Coordinates communication between the component's
class and its template and often involves passing data.
Class
Properties
Template
Methods
Interpolation
Template Class
<h1 innerText={{pageTitle}}></h1>
Directive
Custom HTML element or attribute used to power up
and extend our HTML.
• Custom
• Built-In
Custom Directives
app.component.ts product-list.component.ts
@Component({ @Component({
selector: 'pm-root', selector: 'pm-products',
template: ` templateURL:
<div><h1>{{pageTitle}}</h1>
<pm-products></pm-products> './product-list.component.html'
</div> })
` export class ProductListComponent { }
})
export class AppComponent { }
Angular Built-in Directives
•*ngIf: If logic
Structural
Directives
•*ngFor: For loops
*ngIf Built-In Directive
<div class='table-responsive'>
<table class='table' *ngIf='products && products.length'>
<thead> ...
</thead>
<tbody> ...
</tbody>
</table>
</div>
BrowserModule
AppModule
AppComponent
ProductList -
Component
Imports
Exports
Declarations
Providers
Bootstrap
*ngFor Built-In Directive
<tr *ngFor='let product of products'> Template
<td></td> input variable
<td>{{ product.productName }}</td>
<td>{{ product.productCode }}</td>
<td>{{ product.releaseDate }}</td>
<td>{{ product.price }}</td>
<td>{{ product.starRating }}</td>
</tr>
for…of vs for…in
for…of
let nicknames= ['di', 'boo', 'punkeye'];
• Iterates over iterable for (let nickname of nicknames) {
objects, such as an array. console.log(nickname);
• Result: di, boo, punkeye }
for…in
let nicknames= ['di', 'boo', 'punkeye'];
• Iterates over the
properties of an object. for (let nickname in nicknames) {
console.log(nickname);
• Result: 0, 1, 2 }
*ngFor Built-In Directive
<tr *ngFor='let product of products'>
<td></td>
<td>{{ product.productName }}</td>
<td>{{ product.productCode }}</td>
<td>{{ product.releaseDate }}</td>
<td>{{ product.price }}</td>
<td>{{ product.starRating }}</td>
</tr>
Checklist: Template
Inline template
- For short templates
- Specify the template property
- Use the ES 2015 back ticks for multiple
lines
- Watch syntax
Linked template
- For longer templates
- Specify the templateUrl property
- Define the path to the HTML file
Checklist: Component as a Directive
product-list.component.ts
@Component({
selector: 'pm-products',
templateURL:
'./product-list.component.html'
})
export class ProductListComponent { }
app.component.ts app.module.ts
@Component({ @NgModule({
selector: 'pm-root', imports: [ BrowserModule ],
template: ` declarations: [
<div><h1>{{pageTitle}}</h1> AppComponent,
<pm-products></pm-products> ProductListComponent ],
</div>` bootstrap: [ AppComponent ]
}) })
export class AppComponent { } export class AppModule { }
Checklist: Interpolation
*ngIf
- Expression is evaluated as a true or false
value
*ngFor
- Define the local variable with let
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | blogs.msmvps.com/deborahk/
Component DOM
EVENTS
PROPERTIES
Module
Overview Property Binding
Handling Events with Event Binding
Handling Input with Two-way Binding
Transforming Data with Pipes
Application Architecture
Welcome
Component
<img src={{product.imageUrl}}>
<img Element
src=' Template
' '{{product.imageUrl}}'>
[ ] http://openclipart.org/
Binding
Property
Target Binding
Expression
Source
Event Binding
Template Class
<h1>{{pageTitle}}</h1>
<img [src]='product.imageUrl'>
<button (click)='toggleImage()'>
export class ListComponent {
pageTitle: string = 'Product List';
https://developer.mozilla.org/en-US/docs/Web/Events
products: any[] = […];
toggleImage(): void {…}
() ''
}
Target Event Template
Statement
Two-way Binding
Template Class
<input [(ngModel)]='listFilter'>
export class ListComponent {
listFilter: string = 'cart';
}
Two-way Binding
Template Class
<input [(ngModel)]='listFilter'>
export class ListComponent {
listFilter: string = 'cart';
}
Two-way Binding
Template Class
<input [(ngModel)]='listFilter'>
export class ListComponent {
listFilter: string = 'cart';
}
Two-way Binding
Template Class
<input [(ngModel)]='listFilter'>
export class ListComponent {
listFilter: string = 'cart';
}
[()]
Banana in a Box
BrowserModule
AppModule
AppComponent
ProductList -
Component
Imports
Exports
Declarations
Providers
Bootstrap
BrowserModule FormsModule
AppModule
AppComponent
ProductList -
Component
Imports
Exports
Declarations
Providers
Bootstrap
Transforming Data with Pipes
Built-in pipes
Transform
bound • date
• number, decimal, Custom
properties percent, currency pipes
before • json, slice
display • etc
Pipe Examples
{{ product.productCode | lowercase }}
<img [src]='product.imageUrl'
[title]='product.productName | uppercase'>
{{ product.price | currency:'USD':true:'1.2-2' }}
Data Binding
DOM product-list.component.ts
@Component({
selector: 'pm-products',
templateURL: './product-list.component.html'
})
export class ProductListComponent {
pageTitle: string = 'Product List';
listFilter: string = 'cart';
products: any[] = […];
toggleImage(): void {…}
}
Data Binding
Interpolation: {{pageTitle}}
DOM Component
Event Binding: <button (click)='toggleImage()'>
product-list.component.html app.module.ts
<div class='col-md-4'> @NgModule({
<input type='text' imports: [
[(ngModel)]='listFilter' /> BrowserModule,
</div> FormsModule ],
declarations: [
AppComponent,
ProductListComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Checklist: Pipes
Pipe character |
Pipe name
Pipe parameters
- Separated with colons
Example
- {{ product.price |
currency:'USD':true:'1.2-2' }}
Summary Property Binding
Handling Events with Event Binding
Handling Input with Two-way Binding
Transforming Data with Pipes
Application Architecture
Welcome
Component
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | blogs.msmvps.com/deborahk/
Improving Our Components
Encapsulating styles
Lifecycle hooks
Custom pipes
Nested components
Module
Overview Defining an Interface
Encapsulating Component Styles
Using Lifecycle Hooks
Building a Custom Pipe
Application Architecture
Welcome
Component
toggleImage(): void {
this.showImage = !this.showImage;
}
toggleImage(): void {
this.showImage = !this.showImage;
}
}
Handling Unique Component Styles
styleUrls
•
@Component({
• selector: 'pm-products',
• templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.css']})
•
Component Lifecycle
Create
and Process
Create Render Destroy
render changes
children
Component Lifecycle Hooks
ngOnInit(): void {
console.log('In OnInit');
}
}
Transforming Data with Pipes
Built-in pipes
Transform
bound • date
• number, decimal, Custom
properties percent, currency pipes
before • json, slice
display • etc
Building a Custom Pipe
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'convertToSpaces'
})
export class ConvertToSpacesPipe
implements PipeTransform {
transform(value: string,
character: string): string {
}
}
Using a Custom Pipe
Template
Pipe
transform(value: string, character: string): string {
}
BrowserModule FormsModule
AppModule
AppComponent
ProductList -
Component
ConvertToSpaces
Pipe
Imports
Exports
Declarations
Providers
Bootstrap
Using a Custom Pipe
Template
Implementing interfaces:
- implements keyword & interface name
- Write code for each property & method
Checklist: Encapsulating Styles
styles property
- Specify an array of style strings
styleUrls property
- Specify an array of stylesheet paths
Checklist: Using Lifecycle Hooks
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | blogs.msmvps.com/deborahk/
Using a Component
App Full
Component page
OR Nested style
Component view
<body>
<pm-root></pm-root>
</body>
What Makes a Component Nest-able?
Class
Class
Building a Nested Component
Container Component
Template
Nested Component
<pm-star> </pm-star>
Template
Input
Output
Class
Class
Product List View
Product List View
Using a Nested Component as a Directive
product-list.component.ts star.component.ts
@Component({ @Component({
selector: 'pm-products', selector: 'pm-star',
templateURL: './product-list.component.html' templateURL: './star.component.html'
}) })
export class ProductListComponent { } export class StarComponent {
rating: number;
starWidth: number;
product-list.component.html }
<td>
{{ product.starRating | number }}
</td>
Using a Nested Component as a Directive
product-list.component.ts star.component.ts
@Component({ @Component({
selector: 'pm-products', selector: 'pm-star',
templateURL: './product-list.component.html' templateURL: './star.component.html'
}) })
export class ProductListComponent { } export class StarComponent {
rating: number;
starWidth: number;
product-list.component.html }
<td>
<pm-star></pm-star>
</td>
BrowserModule FormsModule
AppModule
AppComponent
ProductList -
Component
ConvertToSpaces
Pipe
Imports
Exports
Declarations StarComponent
Providers
Bootstrap
Telling Angular About Our Component
app.module.ts
...
import { StarComponent } from './shared/star.component';
@NgModule({
imports: [
BrowserModule,
FormsModule ],
declarations: [
AppComponent,
ProductListComponent,
ConvertToSpacesPipe,
StarComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Passing Data to a Nested Component (@Input)
Container Component
Template
Nested Component
<pm-star> </pm-star>
Template
Input @Input()
Class
Class
Passing Data to a Nested Component (@Input)
product-list.component.ts star.component.ts
@Component({ @Component({
selector: 'pm-products', selector: 'pm-star',
templateURL: './product-list.component.html' templateURL: './star.component.html'
}) })
export class ProductListComponent { } export class StarComponent {
@Input() rating: number;
starWidth: number;
product-list.component.html }
<td>
<pm-star></pm-star>
</td>
Passing Data to a Nested Component (@Input)
product-list.component.ts star.component.ts
@Component({ @Component({
selector: 'pm-products', selector: 'pm-star',
templateURL: './product-list.component.html' templateURL: './star.component.html'
}) })
export class ProductListComponent { } export class StarComponent {
@Input() rating: number;
starWidth: number;
product-list.component.html }
<td>
<pm-star [rating]='product.starRating'>
</pm-star>
</td>
Raising an Event (@Output)
Container Component
Template
Nested Component
<pm-star> </pm-star>
Template
Input @Input()
Output @Output()
Class
Class
Raising an Event (@Output)
product-list.component.ts star.component.ts
@Component({ @Component({
selector: 'pm-products', selector: 'pm-star',
templateURL: './product-list.component.html' templateURL: './star.component.html'
}) })
export class ProductListComponent { } export class StarComponent {
@Input() rating: number;
starWidth: number;
@Output() notify: EventEmitter<string> =
new EventEmitter<string>();
}
product-list.component.html
<td>
<pm-star [rating]='product.starRating'>
</pm-star>
</td>
Raising an Event (@Output)
product-list.component.ts star.component.ts
@Component({ @Component({
selector: 'pm-products', selector: 'pm-star',
templateURL: './product-list.component.html' templateURL: './star.component.html'
}) })
export class ProductListComponent { } export class StarComponent {
@Input() rating: number;
starWidth: number;
@Output() notify: EventEmitter<string> =
new EventEmitter<string>();
onClick() {
this.notify.emit('clicked!');
product-list.component.html }
}
<td>
<pm-star [rating]='product.starRating'> star.component.html
</pm-star> <div (click)='onClick()'>
</td> ... stars ...
</div>
Raising an Event (@Output)
product-list.component.ts star.component.ts
@Component({ @Component({
selector: 'pm-products', selector: 'pm-star',
templateURL: './product-list.component.html' templateURL: './star.component.html'
}) })
export class ProductListComponent { } export class StarComponent {
@Input() rating: number;
starWidth: number;
@Output() notify: EventEmitter<string> =
new EventEmitter<string>();
onClick() {
this.notify.emit('clicked!');
product-list.component.html }
}
<td>
<pm-star [rating]='product.starRating' star.component.html
(notify)='onNotify($event)'> <div (click)='onClick()'>
</pm-star> ... stars ...
</td> </div>
Raising an Event (@Output)
product-list.component.ts star.component.ts
@Component({ @Component({
selector: 'pm-products', selector: 'pm-star',
templateURL: './product-list.component.html' templateURL: './star.component.html'
}) })
export class ProductListComponent { export class StarComponent {
onNotify(message: string): void { } @Input() rating: number;
} starWidth: number;
@Output() notify: EventEmitter<string> =
new EventEmitter<string>();
onClick() {
this.notify.emit('clicked!');
product-list.component.html }
}
<td>
<pm-star [rating]='product.starRating' star.component.html
(notify)='onNotify($event)'> <div (click)='onClick()'>
</pm-star> ... stars ...
</td> </div>
Nest-able Component's Public API
Container Component
Template
Nested Component
<pm-star> </pm-star>
Template
Input @Input()
Output @Output()
Class
Class
Checklist: Nested Component
Input decorator
- Attached to a property of any type
- Prefix with @; Suffix with ()
Output decorator
- Attached to a property declared as an
EventEmitter
- Use the generic argument to define the
event payload type
- Use the new keyword to create an
instance of the EventEmitter
- Prefix with @; Suffix with ()
Checklist: Container Component
Use the directive
- Directive name -> nested component's
selector
Use property binding to pass data to the
nested component
Use event binding to respond to events
from the nested component
- Use $event to access the event payload
passed from the nested component
Building a Nested Component
Summary
Using a Nested Component
Passing Data to a Nested Component
Using @Input
Raising an Event from a Nested
Component Using @Output
Application Architecture
Welcome
Component
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | blogs.msmvps.com/deborahk/
Products Logging
Service
A class with a focused purpose.
Used for features that:
• Are independent from any particular component
• Provide shared data or logic across components
• Encapsulate external interactions
Module
Overview How Does It Work?
Building a Service
Registering the Service
Injecting the Service
Application Architecture
Welcome
Component
Service Component
export class myService {} let svc = new myService();
svc
How Does It Work?
Injector
Service Component
export class myService {} constructor(private _myService) {}
Dependency Injection
A coding pattern in which a class receives the instances
of objects it needs (called dependencies) from an
external source rather than creating them itself.
Building a Service
Import
what we
need
Define the
metadata
with a
decorator
Create the
service class
Building a Service
product.service.ts
import { Injectable } from '@angular/core'
@Injectable()
export class ProductService {
getProducts(): IProduct[] {
}
}
Registering the Service
Injector
Service Component
export class myService {} constructor(private _myService) {}
Registering a Service
Register a provider
- Code that can create or return a service
- Typically the service class itself
@Component({
selector: 'pm-root',
template: `
<div><h1>{{pageTitle}}</h1>
<pm-products></pm-products>
</div>
`,
providers: [ProductService]
})
export class AppComponent { }
Injecting the Service
Injector
Service Component
export class myService {} constructor(private _myService) {}
Injecting the Service
product-list.component.ts
...
@Component({
selector: 'pm-products',
templateUrl: './product-list.component.html'
})
export class ProductListComponent {
constructor() {
}
}
Injecting the Service
product-list.component.ts
...
import { ProductService } from './product.service';
@Component({
selector: 'pm-products',
templateUrl: './product-list.component.html'
})
export class ProductListComponent {
private _productService;
constructor(productService: ProductService) {
_productService = productService;
}
}
Injecting the Service
product-list.component.ts
...
import { ProductService } from './product.service';
@Component({
selector: 'pm-products',
templateUrl: './product-list.component.html'
})
export class ProductListComponent {
}
Checklist: Creating a Service
Service class
- Clear name
- Use PascalCasing
- Append "Service" to the name
- export keyword
Service decorator
- Use Injectable
- Prefix with @; Suffix with ()
Component metadata
- Set the providers property
- Pass in an array
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | blogs.msmvps.com/deborahk/
Web
Web Browser Server
index.html index.html
JavaScript JavaScript
(http://mysite/api/products/5)
Web
Service
Response
Data
DB
Module
Overview Observables and Reactive Extensions
Sending an Http Request
Exception Handling
Subscribing to an Observable
Application Architecture
Welcome
Component
Promise Observable
Provides a single future value Emits multiple values over time
Not lazy Lazy
Not cancellable Cancellable
Supports map, filter, reduce and similar
operators
Application Architecture
Welcome
Component
Get GET
@Injectable()
export class ProductService {
private _productUrl = 'www.myWebService.com/api/products';
getProducts() {
return this._http.get(this._productUrl);
}
}
Registering the Http Service Provider
app.module.ts
...
import { HttpClientModule } from '@angular/common/http';
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpClientModule ],
declarations: [
AppComponent,
ProductListComponent,
ConvertToSpacesPipe,
StarComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
BrowserModule FormsModule HttpClientModule
AppModule
AppComponent
ProductList -
Component
ConvertToSpaces
Pipe
Imports
Exports
Declarations StarComponent
Providers
Bootstrap
Sending an Http Request
product.service.ts
...
import { HttpClient } from '@angular/common/http';
@Injectable()
export class ProductService {
private _productUrl = 'www.myWebService.com/api/products';
getProducts() {
return this._http.get(this._productUrl);
}
}
Sending an Http Request
product.service.ts
...
import { HttpClient } from '@angular/common/http';
@Injectable()
export class ProductService {
private _productUrl = 'www.myWebService.com/api/products';
getProducts() {
return this._http.get<IProduct[]>(this._productUrl);
}
}
Sending an Http Request
product.service.ts
...
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class ProductService {
private _productUrl = 'www.myWebService.com/api/products';
getProducts(): Observable<IProduct[]> {
return this._http.get<IProduct[]>(this._productUrl);
}
}
Exception Handling
product.service.ts
...
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
...
getProducts(): Observable<IProduct[]> {
return this._http.get<IProduct[]>(this._productUrl)
.do(data => console.log('All: ' + JSON.stringify(data)))
.catch(this.handleError);
}
product-list.component.ts
ngOnInit(): void {
this._productService.getProducts()
.subscribe(products => this.products = products,
error => this.errorMessage = <any>error);
}
Http Checklist: Setup
Pluralsight Courses
- "Angular: Reactive Forms"
• Http and CRUD
- "Play by Play: Angular 2/RxJS/HTTP and
RESTful Services with John Papa and
Dan Wahlin"
• RxJS and Observables
Application Architecture
Welcome
Component
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | blogs.msmvps.com/deborahk/
Module
Overview How Does Routing Work?
Configuring Routes
Tying Routes to Actions
Placing the Views
Application Architecture
Welcome
Component
AppModule
AppComponent
ProductList -
Component
ConvertToSpaces
Pipe
Imports
Exports
Declarations StarComponent
Providers
Bootstrap
BrowserModule FormsModule HttpClientModule
AppModule
ProductDetail -
AppComponent
Component
ProductList -
WelcomeComponent
Component
ConvertToSpaces
Pipe
Imports
Exports
Declarations StarComponent
Providers
Bootstrap
How Routing Works
product-list.component.ts
import { Component } from '@angular/core';
<router-outlet></router-outlet> @Component({
templateUrl: './product-list.component.html'
})
export class ProductListComponent { }
'products', ProductListComponent
'products/:id', ProductDetailComponent
'welcome', WelcomeComponent
Configuring Routes
app.module.ts
...
import { RouterModule } from '@angular/router';
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
RouterModule
],
declarations: [
...
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Configuring Routes
app.module.ts
...
import { RouterModule } from '@angular/router';
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
RouterModule.forRoot([])
],
declarations: [
...
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Configuring Routes
app.module.ts
...
import { RouterModule } from '@angular/router';
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
RouterModule.forRoot([], { useHash: true })
],
declarations: [
...
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Configuring Routes
[
{ path: 'products', component: ProductListComponent },
{ path: 'products/:id', component: ProductDetailComponent },
{ path: 'welcome', component: WelcomeComponent },
{ path: '', redirectTo: 'welcome', pathMatch: 'full' },
{ path: '**', component: PageNotFoundComponent }
]
Navigating the Application Routes
@Component({
selector: 'pm-root',
template: `
<ul class='nav navbar-nav'>
<li><a>Home</a></li>
<li><a>Product List</a></li>
</ul>
`
})
Tying Routes to Actions
app.component.ts
...
@Component({
selector: 'pm-root',
template: `
<ul class='nav navbar-nav'>
<li><a [routerLink]="['/welcome']">Home</a></li>
<li><a [routerLink]="['/products']">Product List</a></li>
</ul>
`
})
Placing the Views
app.component.ts
...
@Component({
selector: 'pm-root',
template: `
<ul class='nav navbar-nav'>
<li><a [routerLink]="['/welcome']">Home</a></li>
<li><a [routerLink]="['/products']">Product List</a></li>
</ul>
<router-outlet></router-outlet>
`
})
How Routing Works
product-list.component.ts
import { Component } from '@angular/core';
<router-outlet></router-outlet> @Component({
templateUrl: './product-list.component.html'
})
export class ProductListComponent { }
Checklist: Displaying Components
Nest-able components
- Define a selector
- Nest in another component
- No route
Routed components
- No selector
- Configure routes
- Tie routes to actions
Checklist: Doing Routing
Configure routes
Tie routes to actions
Place the view
Routing Checklist: Configuring Routes
Define the base element
Add RouterModule
- Add each route (RouterModule.forRoot)
- Order matters
component
- Not string name; not enclosed in quotes
Routing Checklist: Tying Routes to Actions
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | blogs.msmvps.com/deborahk/
Module
Overview
Passing Parameters to a Route
Activating a Route with Code
Protecting Routes with Guards
Application Architecture
Welcome
Component
app.module.ts
{ path: 'products/:id', component: ProductDetailComponent }
Reading Parameters from a Route
product-detail.component.ts
import { ActivatedRoute } from '@angular/router';
app.module.ts
{ path: 'products/:id', component: ProductDetailComponent }
Activating a Route with Code
Activating a Route with Code
product-detail.component.ts
import { Router } from '@angular/router';
...
constructor(private _router: Router) { }
onBack(): void {
this._router.navigate(['/products']);
}
Protecting Routes with Guards
CanActivate
- Guard navigation to a route
CanDeactivate
- Guard navigation from a route
Resolve
- Pre-fetch data before activating a route
CanLoad
- Prevent asynchronous routing
Building a Guard
product-guard.service.ts
import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
@Injectable()
export class ProductGuardService implements CanActivate {
canActivate(): boolean {
...
}
}
Registering a Guard
app.module.ts
...
import { ProductGuardService } from './products/product-guard.service';
@NgModule({
imports: [...],
declarations: [...],
providers: [ ProductGuardService ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Using a Guard
app.module.ts
@NgModule({
imports: [
...,
RouterModule.forRoot([
{ path: 'products', component: ProductListComponent },
{ path: 'products/:id',
canActivate: [ProductGuardService ],
component: ProductDetailComponent },
...])
],
declarations: [...],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Routing Checklist: Passing Parameters
app.module.ts
{ path: 'products/:id', component: ProductDetailComponent }
product-list.component.html
<a [routerLink]="['/products', product.productId]">
{{product.productName}}
</a>
product-detail.component.ts
import { ActivatedRoute } from '@angular/router';
"Angular Routing"
- Required, optional, & query parameters
- Prefetching with route resolvers
- Child and secondary router outlets
- Router guards
- Lazy loading
BrowserModule FormsModule HttpClientModule RouterModule
AppModule
ProductDetail -
AppComponent ProductService
Component
ProductList -
WelcomeComponent ProductGuardService
Component
ConvertToSpaces
Pipe
Imports
Exports
Declarations StarComponent
Providers
Bootstrap
Angular Modules
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | blogs.msmvps.com/deborahk/
BrowserModule
ProductList -
AppComponent ProductService StarComponent
Component
ProductDetail -
WelcomeComponent ProductGuardService CommonModule
Component
Imports ConvertToSpaces
FormsModule
Exports Pipe
Declarations
Providers
Bootstrap
Module
Overview What Is an Angular Module?
Angular Module Metadata
Creating a Feature Module
Defining a Shared Module
Revisiting AppModule
What Is an Angular Module?
@angular
@angular @angular
@angular
module Module module Module
module Imports Exports module
Module
Imports
Componen Component,
Exports Service
t Component
Directive,
Declarations
Pipe
Providers
Bootstrap
AppComponent ... RouterModule
<li><a [routerLink]="['/welcome']">
ProductList -
Home</a></li>
Component <li><a [routerLink]="['/products']">
Product List</a></li>
ProductDetail - ...
Component <router-outlet></router-outlet>
...
WelcomeComponent
Angular Module
AppComponent RouterModule
WelcomeComponent
Angular Module
AppComponent RouterModule
Angular Module
ConvertToSpaces
AppComponent RouterModule
Pipe
Angular Module
ConvertToSpaces
AppComponent RouterModule
Pipe
Angular Module
ConvertToSpaces
AppComponent RouterModule
Pipe
ProductList -
StarComponent FormsModule
Component
ProductDetail -
BrowserModule
Component
WelcomeComponent
Angular Module
Template Resolution Environment
Star-
Module
Component
Forms-
Module
Module
ProductList- Star-
Imports Component Component
Exports
Declarations
Providers
Bootstrap
Bootstrap Array
app.module.ts
AppModule
...
bootstrap: [ AppComponent ]
AppComponent ...
Bootstrap
Bootstrap Array Truth #1
Every application must bootstrap at least one
component, the root application component.
Bootstrap Array Truth #2
The bootstrap array should only be used in the root
application module, AppModule.
Declarations Array
app.module.ts
Module
...
declarations: [
AppComponent,
WelcomeComponent,
Declares
ProductListComponent,
ProductDetailComponent,
ConvertToSpacesPipe,
StarComponent
Component, ]
Component
Directive, ...
Pipe
Declarations
Declarations Array Truth #1
Every component, directive, and pipe we create must
belong to one and only one Angular module.
Declarations Array Truth #2
Only declare components, directives and pipes.
Declarations Array Truth #3
Never re-declare components, directives, or pipes that
belong to another module
Module A Module B
Imports
ProductList- Star-
Exports
Component Component
Declarations
Declarations Array Truth #4
All declared components, directives, and pipes are
private by default.
Module B
They are only accessible to
other components, directives,
and pipes declared in the
Star-
same module. Component
Exports
Declarations
Declarations Array Truth #5
The Angular module provides the template resolution
environment for its component templates.
product-list.component.html star.component.ts
<pm-star ...> ...
</pm-star> @Component({
selector: 'pm-star',
template: ...
})
...
Declarations Array Truth #5
The Angular module provides the template resolution
environment for its component templates.
Module A Module B
Imports
Exports
Declarations ProductList- Star- Star-
Providers Component Component Component
Bootstrap
Exports Array
@angular
@angular
module Module
Exports module
Module
@angular
3rd party Component,
module Component
Directive,
module
Pipe
Imports
Exports
Declarations
Providers
Bootstrap
Exports Array Truth #1
Export any component, directive, or pipe if other
components need it.
Exports Array Truth #2
Re-export modules to re-export their components,
directives, and pipes.
Exports Array Truth #3
We can re-export something without importing it first.
SharedModule
Imports
FormsModule
Exports
Declarations
Providers
Bootstrap
Exports Array Truth #4
Never export a service.
AppModule
Imports ProductGuardService
Exports
Declarations
Providers
Bootstrap
Imports Array
@angular
@angular
module Module
module app.module.ts
...
3rd party Route imports: [
module module BrowserModule,
FormsModule,
Imports HttpClientModule,
RouterModule.forRoot([...])
]
...
Module
Imports Array Truth #1
Importing a module makes available any exported
components, directives, and pipes from that module.
FormsModule
Imports
Exports AppModule
Declarations
Providers
Bootstrap
Imports Array Truth #2
Only import what this module needs.
Imports Array Truth #3
Importing a module does NOT provide access to its
imported modules
FormsModule ngModel
SharedModule StarComponent
ProductList-
AppModule Component
Providers Array
app.module.ts
Module ...
providers: [ ProductGuardService ]
...
app.component.ts
...
Service
providers: [ ProductService ]
...
Imports
Exports
Declarations
Providers
Bootstrap
Providers Array Truth #1
Any service provider added to the providers array is
registered at the root of the application.
ProductModule
Imports
Exports
ProductService
Declarations
Providers
Bootstrap
Providers Array Truth #2
Don't add services to the providers array of a shared
module.
Consider building a CoreModule for services and
importing it once in the AppModule.
Providers Array Truth #3
Routing guards must be added to the providers array of
an Angular module.
BrowserModule FormsModule HttpClientModule RouterModule
AppModule
ProductDetail -
AppComponent ProductGuardService
Component
ProductList -
WelcomeComponent
Component
ConvertToSpaces
Pipe
Imports
Exports
Declarations StarComponent
Providers
Bootstrap
Defining a Feature Module
CommonModule FormsModule RouterModule
AppModule ProductModule
ProductList -
ProductService
Component
ProductDetail -
ProductGuardService Component
Imports ConvertToSpaces
Exports Pipe
Declarations
Providers StarComponent
Bootstrap
Defining a Shared Module
CommonModule
ProductModule SharedModule
StarComponent
CommonModule
Imports
Exports FormsModule
Declarations
Providers
Bootstrap
Revisiting AppModule
BrowserModule
HttpClientModule RouterModule
AppModule ProductModule
AppComponent
Imports
WelcomeComponent
Exports
Declarations
Providers
Bootstrap
FormsModule
CommonModule
ProductModule
ProductList -
ProductService
Component
ProductDetail -
ProductGuardService Component
Imports ConvertToSpaces
Exports Pipe
Declarations
Providers StarComponent
Bootstrap
Application Routing Module
app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
@NgModule({
imports: [
RouterModule.forRoot([
{ path: 'welcome', component: WelcomeComponent },
{ path: '', redirectTo: 'welcome', pathMatch: 'full'},
{ path: '**', redirectTo: 'welcome', pathMatch: 'full' }
])
],
exports: [ RouterModule ]
})
export class AppRoutingModule { };
Using the Routing Module
app.module.ts
@NgModule({
imports: [
BrowserModule,
HttpClientModule,
ProductModule,
AppRoutingModule
],
declarations: [ AppComponent, WelcomeComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Using the Routing Module
app.module.ts
@NgModule({
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule,
ProductModule
],
declarations: [ AppComponent, WelcomeComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Feature Routing Module
product-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { ProductListComponent } from './product-list.component';
import { ProductDetailComponent } from './product-detail.component';
import { ProductGuardService } from './product-guard.service';
@NgModule({
imports: [
RouterModule.forChild([
{ path: 'products', component: ProductListComponent },
{ path: 'products/:id', canActivate: [ ProductGuardService],
component: ProductDetailComponent }
])
],
exports: [ RouterModule ]
})
export class ProductRoutingModule { };
Using the Routing Module
product.module.ts
@NgModule({
imports: [
SharedModule,
ProductRoutingModule
],
declarations: [
ProductListComponent,
ProductDetailComponent,
ConvertToSpacesPipe
],
providers: [
ProductService,
ProductGuardService
]
})
export class ProductModule {}
Angular Module Checklist: Module Structure
AppModule
ProductDetail -
AppComponent ProductGuardService
Component
ProductList -
WelcomeComponent
Component
ConvertToSpaces
Pipe
Imports
Exports
Declarations StarComponent
Providers
Bootstrap
BrowserModule
ProductList -
AppComponent ProductService StarComponent
Component
ProductDetail -
WelcomeComponent ProductGuardService CommonModule
Component
Imports ConvertToSpaces
FormsModule
Exports Pipe
Declarations
Providers
Bootstrap
Up Next
Angular CLI
Building, Testing, and Deploying
with the CLI
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | blogs.msmvps.com/deborahk/
Module Overview
Overview ng new
ng serve
ng generate
ng test
ng build
Angular CLI Overview
ng new
Demo
ng serve
Demo
ng generate
Demo
ng test
ng e2e
Demo
ng build
Angular CLI Checklist: Commands
ng help - Displays commands and flags
ng new - Creates new Angular application
ng serve - Launches a server
ng generate - Generates file from blueprint
ng test - Runs unit tests using Karma
ng e2e - Runs end to end tests using Protractor
ng build - Compiles into an output directory
Angular CLI Checklist: ng generate
class ng g cl
component ng g c
directive ng g d
enum ng g e
guard ng g g
interface ng g i
module ng g m
pipe ng g p
service ng g s
Overview
Summary ng new
ng serve
ng generate
ng test
ng build
Learning More
"Angular CLI"
- John Papa
Final Words
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | blogs.msmvps.com/deborahk/
What Is a Component?
Class
= + +
Properties
Component Template Metadata
Methods
Where Do We Put the Html?
Interpolation: {{pageTitle}}
DOM Component
Event Binding: <button (click)='toggleImage()'>
Application
= Component
+ Component
+ Component …
Services
How Do We Build?
product-list.component.ts
import { Component } from '@angular/core';
@Component({
templateUrl: './product-list.component.html',
styleUrls: './product-list.component.css'
})
export class ProductListComponent {
pageTitle: string = 'Product List';
}
BrowserModule
How Do We Build?
HttpClientModule RouterModule RouterModule CommonModule
ProductList -
AppComponent ProductService StarComponent
Component
ProductDetail -
WelcomeComponent ProductGuardService CommonModule
Component
Imports ConvertToSpaces
FormsModule
Exports Pipe
Declarations
Providers
Bootstrap
Angular CLI
ng new
ng serve
ng generate
ng test & ng e2e
ng build
Checklist
Angular Documentation
- Angular.io
GitHub Repository
https://github.com/DeborahK/Angular-GettingStarted
Angular Is …
A JavaScript framework
For building client-side applications
Using HTML, CSS and JavaScript
Angular Is …
A platform supporting
- Multiple languages (ES5, TypeScript)
- Multiple templating syntaxes (HTML,
XML)
- Multiple rendering targets (DOM, native)
Mobile Web
- Material design
- Angular Universal
- Web Workers