@laco2net
2017-09-24 HTML5 Conference
Why is Angular popular?
@Component({
selector: "app-profile",
template: "<p>Name: {{ name }}</p>"
})
class ProfileComponent {
@Input() name: string;
}
<div>
<app-profile name="laco"></app-profile>
</div>
Data-Binding: [prop]
@Component({
template: `
<input [value]="name">
<div [attr.role]="role"></div>
<div [class.large]="isLarge"></div>
<div [style.width.px]="mySize"></div>
`
})
class MyComponent {
name = "laco";
role = "main"
isLarge = true;
mySize = 16;
}
Event Handling: (event)
@Component({
template: `
<button (click)="onClick($event)">
`
})
class MyComponent {
onClick(e: MouseEvent) {
}
}
# Install Angular CLI
> npm install -g @angular/cli
# Create new app
> ng new hello-angular
# Test
> ng test
# Build
> ng build --prod
# Debug
> ng serve
Easy to develop Angular apps
@angular/core
@angular/common
@angular/forms
@angular/http
@angular/router
@angular/material
@angular/platform-server
@angular/service-worker
@angular/language-service
...
Static Type
Decorators
Type-base Dependency Injection
Language Services
Benefit of Type
Code as Living API doc
Always correct
Compiler check
Compilation is the easiest test
Auto-completions
Language Services Helps your editor
Spec: javascript-decorators
Status: tc39/proposals
tsc --experimentalDecorators
"Typo-safe" DI
Good-bye "$http"
import {Http} from "@angular/http";
@Injectable()
class MyService {
constructor(private anyNameForHttp: Http) {
}
}
Types in the template
@Component()
@Input() / @Output()
@Directive()
@Pipe()
@NgModule()
It's a component because it composes app
import {Component} from '@angular/core';
@Component({
selector: 'my-app',
template: `
<h1>{{title}}</h1>
`,
styles: [`h1 { color: blue; }`]
})
export class MyAppComponent {
title = 'Hello World!';
}
Top-down Data Flow: @Input()
@Component({
selector: 'my-app',
template: `<profile [name]="myName"></profile>`
})
class MyAppComponent {
myName = 'laco';
}
@Component({
selector: 'profile',
template: `<p>{{name}}</p>`
})
class ProfileComponent {
@Input() name;
}
Bottom-up Event System: @Output()
@Component({
selector: 'my-app',
template: `<app-menu (select)="onMenuSelect($event)"></app-menu>`
})
class MyAppComponent {
onMenuSelect(menuItem) { }
}
@Component({
selector: 'app-menu',
template: `...`
})
class MenuComponent {
@Output() select = new EventEmitter();
selectMenu(menuItem) { this.select.emit(menuItem); }
}
Extend elements
import {Directive, HostBinding} from '@angular/core';
@Directive({
selector: '[underline]'
})
class BootstrapBtn {
@HostBinding('style') hostStyle = "text-decoration: underline";
}
<span underline>Text</span>
<span style="text-decoration: underline">Text</span>
Data transformer
import {Pipe} from '@angular/core';
@Pipe({
name: 'quote'
})
class QuotePipe {
transform(value) {
return `"${value}"`;
}
}
<p>{{ message | quote }}</p>
Module
Components
Application
Platform
Directives
Pipes
Module
Module
Module
Services
Application Configuration
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {MyAppComponent} from './app.component';
import {MyOtherComponent} from './other.component';
import {MyService} from './my.service';
@NgModule({
imports: [BrowserModule],
declarations: [MyOtherComponent, MyAppComponent],
providers: [MyService],
bootstrap: [MyAppComponent]
})
export class MyAppModule {}
Application Environment
import {
platformBrowser
} from '@angular/platform-browser';
import {
platformBrowserDynamic
} from '@angular/platform-browser-dynamic';
import {
platformServer
} from '@angular/platform-server';
import {MyAppModule} from './app.module';
platformBrowserDynamic().bootstrapModule(MyAppModule);
Angular Ecosystem
Render View
Watch model's change
Transit View
Access to Server
@Component({
template: "<h1>{{title}}</h1>"
})
class MyComponent {
title = "Hello!";
}
<h1>Hello!</h1>
URL-Component Mapping
Guard & Resolve
Nesting
Lazy-Loading
@Injectable()
export class HeroService {
constructor (private http: HttpClient) {}
getHeroes (): Observable<Hero[]> {
return this.http.get<Hero[]>("/api/heroes");
}
addHero (hero: Hero): Observable<Hero> {
return this.http.post<Hero>("/api/heroes", hero);
}
}
Wrap XHR/JSONP
Return Observable<T>
Lazy-Execution
Aborting
Multi-Responses
Interceptor
Progress Event
@Injectable()
export class MyInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
newReq = req.clone({
headers: new HttpHeaders({ 'X-AUTHOR': 'laco' })
});
return next.handle(newReq);
}
}
http.post('/upload/file', file, { reportProgress: true })
.subscribe(event => {
if (event.type === HttpEventType.UploadProgress) {
const percentDone =
Math.round(100 * event.loaded / event.total);
console.log(`File is ${percentDone}% uploaded.`);
} else if (event instanceof HttpResponse) {
console.log('File is completely uploaded!');
}
});
Animations
Server-side Rendering
UI Components
Debugger
Editor Plugins
Developer Tool
@Component({
animations: [
trigger("visibility", [
state("shown", style({ opacity: 1 })),
state("hidden", style({ opacity: 0 })),
transition("* => *", animate(".5s"))
])
],
template: `
<div [@visibility]="visibility">
`
})
class MyComponent() {
visibility = 'hidden';
}
import { renderModule } from '@angular/platform-server';
renderModule(AppServerModule, {
document: fs.readFileSync('src/index.html', 'utf8'),
url: '/'
}).then(html => {
fs.writeFileSync('dist/index.html', html);
});
@angular/platform-server
Scaffold Angular project
Tasks
Generate code
Debug
Test
Lint
Full of Best Practices
VSCode Plugin (Official)
WebStorm (Built-in)
@angular/language-service
Chrome Extension for Angular Debugging
Built on Latest Angular
Progressive Web App
Offline
Add to Homescreen
Source Code
angular/angular: /aio
Read angular.io
Official documentation
Use Angular CLI
Follow the Best Practice
Modern Web => Angular, React, Vue, ...
"The Web has moved.
Frameworks must move"
Angular x.y.z
x: major
Update can contain breaking changes
y: minor
Update cannot breaking changes
z: patch
Only bug fix
Every weak: patch update
Every month: minor update
Every 6 months: major update
Angular is a Platform for Developer Experience
Basic APIs are Simple & Useful
How to learn Angular
Read angular.io
Use Angular CLI
Follow the Best Practice
Understand the Web
Keep an eye on changes