Angular v5.0
@laco2net
2017-10-10 ng-japan Meetup
about me
- 稲富 駿 (laco)
- Kaizen Platform
- ng-japan Organizer
- Angular Contributor
Why is Angular popular?
Angular Overview
Angular
- Web Standards
- Simple
- Easy
- Fast
- Full-stack
- Powered by
Angular Web Standards
- ECMAScript 2015+
- ES Modules
- Web Animations API
- Web Components
-
ES Proposal
- Decorators
- Observables
- Zones
Component definition
@Component({
selector: "app-profile",
template: "<p>Name: {{ name }}</p>"
})
class ProfileComponent {
@Input() name: string;
}
<div>
<app-profile name="laco"></app-profile>
</div>
Template Syntax (1)
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;
}
Template Syntax (2)
Event Handling: (event)
@Component({
template: `
<button (click)="onClick($event)">
`
})
class MyComponent {
onClick(e: MouseEvent) {
}
}
Angular CLI
# 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
High Performance
- Smart Change Detector
- Code Generation
- 100k checks / 10ms
- Reduce detection
- Triggered by Zone.js
- Code Generation
- Smart Renderer
- Reduce DOM manipulations
Official Packages
-
@angular/core
-
@angular/common
-
@angular/forms
-
@angular/http
-
@angular/router
-
@angular/material
-
@angular/platform-server
-
@angular/service-worker
-
@angular/language-service
-
...
TypeScript
-
Static Type
-
Decorators
-
Type-base Dependency Injection
-
Language Services
Language Service
Types in the template
Semantic Versioning
Angular x.y.z
-
x: major
-
Update can contain breaking changes
-
-
y: minor
-
Update cannot breaking changes
-
-
z: patch
-
Only bug fix
-
Time-base Release
-
Every weak: patch update
-
Every month: minor update
-
Every 6 months: major update
Angular v5.0
What’s new?
Animations
- :increment / :decrement
- New Transition Aliases
-
[@anim.disabled]
-
Disable Animations by data-binding
-
-
Negative Query Limit
-
Count from tail
-
:increment / :decrement
@Component({
animations: [
trigger("counter", [
transition(':increment', [ /*...*/ ]),
transition(':decrement', [ /*...*/ ]),
])
],
template: `
<span [@counter]="count">
`
})
class MyComponent() {
count = 1;
}
Disable animations
@Component({
animations: [
trigger("anim", [ /* ... */])
],
template: `
<div [@anim]="prop" [@anim.disabled]="animationDisabled">
`
})
class MyComponent() {
prop = '';
animationDisabled = false;
}
Negative Query Limit
trigger("anim", [
transition(":enter", [
query(
".item",
[ /** ... **/ ],
{ limit: -5 }
)
])
])
Router
-
New Route Events
- ChildActivationStart
- ChildActivationEnd
- ActivationStart
- ActivationEnd
ChildActivationStart/End
router.events
// Event = RouteEvent | RouterEvent
.filter(e => e instanceof RouteEvent)
.subscribe(e => {
if (e instanceof ChildActivationStart) {
spinner.start();
} else if (e instanceof ChildActivationEnd) {
spinner.end()
}
});
ActivationStart/End
router.events
// Event = RouteEvent | RouterEvent
.filter(e => e instanceof RouteEvent)
.subscribe(e => {
if (e instanceof ActivationStart) {
spinner.start();
} else if (e instanceof ActivationEnd) {
spinner.end()
}
});
Forms
-
updateOn
- Control trigger to update
- 'blur' | 'submit' | 'change'
updateOn
<form [ngFormOptions]="{updateOn: 'change'}">
<input name="foo"
[(ngModel)]="foo"
[ngModelOptions]="{updateOn: 'blur'}">
<input name="bar"
[(ngModel)]="bar"
[ngModelOptions]="{updateOn: 'submit'}">
</form>
Core
- Multiple 'exportAs'
- Bootstrap with Custom Zone
Multiple exportAs
@Directive({
selector: 'sushi-maguro',
exportAs: 'maguro, tuna'
})
export class LacoDirective {}
`
<sushi-maguro' #maguro="maguro" #tuna="tuna">
<!-- maguro === tuna -->
</sushi-maguro'>
`
Bootstrap with Custom Zone
platformBrowserDynamic()
.bootstrapModule(AppModule, {
ngZone: 'zone.js' // or 'noop' or Custom NgZone
})
Http
- Object map for HttpClient headers & params
Object map for HttpClient
http.get("/api", {
headers: {
"X-MY-HEADER": "header"
},
params: {
"foo": "bar"
},
})
Platform Server
- TransferState / BrowserTransferStateModule
- Data from server to browser
- Render Hooks
- Callback on serialization
TransferState
const COUNTER_KEY = makeStateKey<number>('counter');
@Component({...})
export class TransferStateComponent {
counter = 0;
constructor(@Inject(PLATFORM_ID) private platformId: {},
private transferState: TransferState) {}
ngOnInit() {
if (isPlatformServer(this.platformId)) {
this.counter = 5;
this.transferState.set(COUNTER_KEY, 50);
} else {
this.counter = this.transferState.get(COUNTER_KEY, 0);
}
}
BEFORE_APP_SERIALIZED
@NgModule({
bootstrap: [MyServerApp],
declarations: [MyServerApp],
imports: [
BrowserModule.withServerTransition({appId: 'render-hook'}),
ServerModule
],
providers: [
{
provide: BEFORE_APP_SERIALIZED,
useFactory: getTitleRenderHook,
multi: true, deps: [DOCUMENT]},
]
})
class RenderHookModule {}
Service Worker
- Rewritten in angular/angular
- @angular/service-worker
- @angular/service-worker/config
- @angular/service-worker/cli
- @angular/service-worker/worker
- experimental feature
Compiler
- Incremental AoT
- ngc --watch
- Powered by TypeScript Custom Transformer
v5 Deprecation
-
@angular/http
- Superseded by HttpClient
v5 Removal
-
Core
-
Drop <template> Support
-
Drop OpaqueToken
-
- Router
- Drop initialNavigation: true | false
- Use 'enable' | 'disable'
- Drop initialNavigation: true | false
- Common
- Drop NgFor directive
- Use NgForOf: <ng-template ngForOf>
- No effects to *ngFor
- Drop NgFor directive
v5 Breaking Changes
-
Require TypeScript >=2.4.x
-
Common Pipes using Intl API
-
Drop dependency on Intl
- Buggy and inconsistent in cross browsers
-
- Switch to Common Locale Data Repository (CLDR)
- Bundle locale data in @angular/common/locales
- Only en_US is enabled by default
- Import locales on demand
- Some formats are changed
- See documentation
Import locales/Ja
import { registerLocaleData } from '@angular/common';
import localeJa from '@angular/common/locales/ja';
registerLocaleData(localeJa);
Use deprecated I18N pipes
import {
CommonModule,
DeprecatedI18NPipesModule
} from '@angular/common';
@NgModule({
imports: [
CommonMudule,
DeprecatedI18NPipesModule,
]
})
export class AppModule {}
Other Updates
Angular Material
Material Beta.12
-
md* => mat*
-
use angular-material-prefix-updater w/ beta.11
-
$ mat-switcher --help
-
-
-
Drop all-in-one MaterialModule
-
MatInputModule
-
<md-input-container> => <mat-form-field>
-
-
All* Components use OnPush
Angular CLI
- Scaffold Angular project
- Generate code
- Debug
- Test
- Lint
- Deploy
Angular CLI Updates
-
--build-optimizer (v1.3) => default in v1.5
-
Optimize AoT-generated code
-
-
platform-server support (v1.3)
-
Build app for Node.js
-
-
Custom Template (v1.4)
-
Schematics: Scaffolding Tool by Angular Team
-
Default templates: @schematics/angular
-
-
--collection option to choose schematics package
-
-
ES2015 Support (v1.5)
-
tsconfig.compilerOptions.target
-
Documentation
angular.io
next.angular.io
v4.angular.io
How to learn Angular?
Learn Angular
-
Read angular.io
-
Official documentation
-
-
Use Angular CLI
-
Follow the Best Practice
-
Watch CHANGELOG
Read Release Note
Read Release Note
Join communities
Conclusion
-
Angular is a Platform for Developer Experience
-
v5 Updates
-
Some new features and removal
-
Breaking changes on I18N pipes
-
-
How to learn Angular
-
Read angular.io
-
Use Angular CLI
-
Follow the Best Practice
-
Keep an eye on changes
-
ng-japan OnAir
ng-japan OnAir
- ng-japan on YouTube Live
- Tech Talks
- Discussions
- Inspired by AngularAir
-
Call for speakers of #1!!
- Go to #on-air channel on Slack!
Thanks!
Angular v5.0
By Suguru Inatomi
Angular v5.0
ng-japan Meetup
- 6,644