Install command-line interface
npm install -g @angular/cli
Generate component
ng generate component components/{component-name}
# generate more
ng generate --help
# serve local
ng serve
# run production build
ng build -c production
# run tests
ng test
# update angular packages
ng update
// update template values from async observable or promise in 'realtime'
@Component({
selector: 'async-observable-pipe',
template: '<div>Time: {{ time | async }}</div>'
})
export class AsyncObservablePipeComponent {
time = new Observable<string>((observer: Observer<string>) => {
setInterval(() => observer.next(new Date().toString()), 1000);
});
}// Passive link (with preventDefault) <a [routerLink]="" (click)="showArticles()">Articles</a>
// Style host element in component.less file
:host {
display:block;
background-color:red;
}
<!-- ng-container does not render a HTML Element --> <ng-container *ngFor="let item of items; let i = index"> <!-- ... --> </ng-container>
*ngFor / ngClass
<div *ngFor="let season of seasons; let i = index" class="filter-item" [ngClass]="{'active': selectedValue == season.value}"></div>
Nested (inline) content
<!-- inside component -->
<div class="dialog-container">
<div class="dialog">
<div class="dialog-header">
<ng-content select="header"></ng-content>
</div>
<div class="dialog-content">
<ng-content select="content"></ng-content>
</div>
</div>
</div>
<!-- outside component -->
<app-inline-dialog>
<header>
<!-- header content -->
</header>
<content>
<!-- content -->
</content>
</app-inline-dialog>
//Reference child component as instance: @ViewChild(SignatureComponent) signaturePad: SignatureComponent;
// NgFor even / odd
<tr *ngFor="let hero of heroes; let even = even; let odd = odd"
[ngClass]="{ odd: odd, even: even }">
<td>{{hero.name}}</td>
</tr>
// NgFor first / last
<tr *ngFor="let hero of heroes; let first = first; let last = last"
[ngClass]="{ first: first, last: last }">
<td>{{hero.name}}</td>
</tr>
// Getter + setter: template code <app-expand-button [(expanded)]="expanded"></app-expand-button>
// Getter + setter: controller code
import { Component, OnInit, EventEmitter, Output, Input } from "@angular/core";
@Component({
selector: "app-expand-button",
templateUrl: "./expand-button.component.html",
styleUrls: ["./expand-button.component.less"]
})
export class ExpandButtonComponent implements OnInit {
public _expanded: boolean;
@Output()
expandedChange: EventEmitter<boolean> = new EventEmitter<boolean>();
@Input()
set expanded(value: boolean) {
if (this._expanded === value)
return;
this._expanded = value;
this.expandedChange.emit(value);
}
constructor() { }
async ngOnInit() { }
}
// Reference to Html element: template
<div #myElementId></div>
// Reference to Html element: controller
@ViewChild("myElementId") myElement: ElementRef;
// Prevent router outlet from flickering
<div class="router-container" [hidden]="!o.isActivated">
<router-outlet #o="outlet"></router-outlet>
</div>
//Inject html element in constructor
constructor(private _element: ElementRef) {
console.log(this._element);
}
// Subscribe to router events
constructor(_router: Router) {
let prevUrl = '';
_router.events.subscribe(event => {
if (event instanceof ActivationEnd) {
const newUrl = _router.url;
const urlEquals = prevUrl === newUrl;
const fromChildUrl = prevUrl.indexOf(newUrl) >= 0;
//console.log('navigate component', prevUrl, '=>', newUrl);
const hasChildren = event.snapshot.children.length > 0;
const componentName = (event.snapshot.component as any).name;
if (!urlEquals && !fromChildUrl && !hasChildren) {
//console.log('activated:', componentName);
this.emitter.emit(Events.componentActivated, componentName)
}
prevUrl = newUrl;
}
});
}
// Subscribe to window events
@HostListener("document:visibilitychange")
onPageVisibilityChanged() {
this.emitter.emit(Events.pageVisibilityChanged, { visible: document.visibilityState === 'visible' });
}
@HostListener("window:online")
@HostListener("window:offline")
onOnlineStatusChanged() {
this.emitter.emit(Events.onlineStatusChanged, { online: window.navigator.onLine });
}
// OnInit + OnDestroy
export class MyComponent extends BaseComponent implements OnInit, OnDestroy {
ngOnInit() {
}
ngOnDestroy() {
}
}
// Null check in template
<div>{{customer?.name}} <span>#{{customer?.customerNumber}}</span></div>
// Relative navigation
this._router.navigate("..", { relativeTo: this._route });
// Use hash for routing + force refresh same route
RouterModule.forRoot(routes, { useHash: true, onSameUrlNavigation: "reload" })
// otherwise route redirect to home
{ path: "**", redirectTo: "/login" }
// Child components: route config
// Use child component with nested <router-outlet> in parent component
{
path: "article-supply",
component: ArticleSupplyComponent,
runGuardsAndResolvers: "always",
canActivate: [AuthGuard],
children: [
{
path: "salesdisplay",
component: SelectSalesDisplayComponent
},
{
path: "new-salesdisplay",
component: SelectSalesDisplayComponent
}
]
}
// track by function example: https://netbasal.com/angular-2-improve-performance-with-trackby-cc147b5104e5
@Component({
selector: 'my-app',
template: `
<ul>
<li *ngFor="let item of collection;trackBy: trackByFn">{{item.id}}</li>
</ul>
<button (click)="getItems()">Refresh items</button>
`,
})
export class App {
constructor() {
this.collection = [{id: 1}, {id: 2}, {id: 3}];
}
getItems() {
this.collection = this.getItemsFromServer();
}
getItemsFromServer() {
return [{id: 1}, {id: 2}, {id: 3}, {id: 4}];
}
trackByFn(index, item) {
return index; // or item.id
}
}
// DeactivateGuard for component deactivation delay for e.g. animations
// 1. In app.module.ts add: providers: [DeactivateGuard]
// 2. In app-routing.module.ts add: canDeactivate: [DeactivateGuard] to each route
// 3. Implement OnDeactivate in each component
import { Injectable, Component } from "@angular/core";
import { CanDeactivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from "@angular/router";
import { Observable } from "rxjs";
// tslint:disable-next-line: naming-convention
export interface OnDeactivate {
onDeactivate(): Promise<boolean>;
}
@Injectable()
export class DeactivateGuard implements CanDeactivate<Component> {
canDeactivate(component: Component, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState?: RouterStateSnapshot)
: Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
if (component && (component as any).onDeactivate) {
const c = component as OnDeactivate;
return c.onDeactivate();
}
return true;
}
}
Create a component dynamically
https://netbasal.com/dynamically-creating-components-with-angular-a7346f4a982d
constructor(private resolver: ComponentFactoryResolver) {}
createComponent(type) {
this.container.clear();
const factory: ComponentFactory = this.resolver.resolveComponentFactory(AlertComponent);
this.componentRef: ComponentRef = this.container.createComponent(factory);
}
https://angular.io/guide/dynamic-component-loader
export class AdBannerComponent implements OnInit, OnDestroy {
@Input() ads: AdItem[] = [];
currentAdIndex = -1;
@ViewChild(AdDirective, {static: true}) adHost!: AdDirective;
interval: number|undefined;
ngOnInit(): void {
this.loadComponent();
this.getAds();
}
ngOnDestroy() {
clearInterval(this.interval);
}
loadComponent() {
this.currentAdIndex = (this.currentAdIndex + 1) % this.ads.length;
const adItem = this.ads[this.currentAdIndex];
const viewContainerRef = this.adHost.viewContainerRef;
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent<AdComponent>(adItem.component);
componentRef.instance.data = adItem.data;
}
getAds() {
this.interval = setInterval(() => {
this.loadComponent();
}, 3000);
}
}169000cookie-checkAngular Tricks