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