Angular Essentials 2 

Lifecycle Hooks
Lifecycle Hooks

ngOnChanges()

import { Component, OnChanges, SimpleChanges } from '@angular/core';

@Component({
...
})
export class AComponent implements OnChanges {
  // only called for/if there is an @input variable set by parent.
  ngOnChanges(changes: SimpleChanges) {
      ...
  }
}

ngOnInit()

import { Component, OnInit } from '@angular/core';

@Component({
...
})
export class AComponent implements OnInit {
  // implement OnInit's `ngOnInit` method
  ngOnInit() {
      ...
  }
}

ngDoCheck()

import { Component, DoCheck } from '@angular/core';

@Component({
...
})
export class AComponent implements DoCheck {
  // Beware! Called frequently!
  // Called in every change detection cycle anywhere on the page
  ngDoCheck() {
      ...
  }
}

ngAfterContentInit()

import { Component, AfterContentInit } from '@angular/core';

@Component({
...
})
export class AComponent implements AfterContentInit {
  ngAfterContentInit() {
      ...
  }
}

ngAfterContentChecked()

import { Component, AfterContentChecked } from '@angular/core';

@Component({
...
})
export class AComponent implements AfterContentChecked {
  // Beware! Called frequently!
  // Called in every change detection cycle anywhere on the page
  ngAfterContentChecked() {
      ...
  }
}

ngAfterViewInit()

import { Component, AfterViewInit } from '@angular/core';

@Component({
...
})
export class AComponent implements AfterViewInit {
  ngAfterViewInit() {
      ...
  }
}

ngAfterViewChecked()

import { Component, AfterViewChecked } from '@angular/core';

@Component({
...
})
export class AComponent implements AfterViewChecked {
  // Beware! Called frequently!
  // Called in every change detection cycle anywhere on the page
  ngAfterViewChecked() {
      ...
  }
}

ngOnDestroy()

import { Component, OnDestroy } from '@angular/core';

@Component({
...
})
export class AComponent implements OnDestroy {
  ngOnDestroy() {
      ...
  }
}
Structural directive
The asterisk (*) prefix

# Sugared directive
<div *ngIf="hero" >{{hero.name}}</div>

# Desugar step 1
<div template="ngIf hero">{{hero.name}}</div>

# Desugar step 2
<ng-template [ngIf]="hero">
  <div>{{hero.name}}</div>
</ng-template>
ngIf
<p *ngIf="true">
  Expression is true and ngIf is true.
  This paragraph is in the DOM.
</p>
<p *ngIf="false">
  Expression is false and ngIf is false.
  This paragraph is not in the DOM.
</p>
ngFor
<div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd">
  ({{i}}) {{hero.name}}
</div>
ngFor
<div *ngFor="
    let hero of heroes;
    let i=index;
    let odd=odd;
    trackBy: trackById"
[class.odd]="odd">
  ({{i}}) {{hero.name}}
</div>

<div template="
    ngFor let hero of heroes; 
    let i=index; 
    let odd=odd; 
    trackBy: trackById" 
[class.odd]="odd">
  ({{i}}) {{hero.name}}
</div>

<ng-template 
    ngFor 
    let-hero 
    [ngForOf]="heroes" 
    let-i="index" 
    let-odd="odd" 
    [ngForTrackBy]="trackById">
  <div [class.odd]="odd">({{i}}) {{hero.name}}</div>
</ng-template>
ngSwitch
<div [ngSwitch]="hero?.emotion">
  <happy-hero    *ngSwitchCase="'happy'"    [hero]="hero"></happy-hero>
  <sad-hero      *ngSwitchCase="'sad'"      [hero]="hero"></sad-hero>
  <confused-hero *ngSwitchCase="'confused'" [hero]="hero"></confused-hero>
  <unknown-hero  *ngSwitchDefault           [hero]="hero"></unknown-hero>
</div>
ngSwitch
<div [ngSwitch]="hero?.emotion">
  <happy-hero    template="ngSwitchCase 'happy'"    [hero]="hero"></happy-hero>
  <sad-hero      template="ngSwitchCase 'sad'"      [hero]="hero"></sad-hero>
  <confused-hero template="ngSwitchCase 'confused'" [hero]="hero"></confused-hero>
  <unknown-hero  template="ngSwitchDefault"         [hero]="hero"></unknown-hero>
</div>
<div [ngSwitch]="hero?.emotion">
  <ng-template [ngSwitchCase]="'happy'">
    <happy-hero [hero]="hero"></happy-hero>
  </ng-template>
  <ng-template [ngSwitchCase]="'sad'">
    <sad-hero [hero]="hero"></sad-hero>
  </ng-template>
  <ng-template [ngSwitchCase]="'confused'">
    <confused-hero [hero]="hero"></confused-hero>
  </ng-template >
  <ng-template ngSwitchDefault>
    <unknown-hero [hero]="hero"></unknown-hero>
  </ng-template>
</div>

Group sibling elements

<select [(ngModel)]="hero">
  <ng-container *ngFor="let h of heroes">
    <ng-container *ngIf="showSad || h.emotion !== 'sad'">
      <option [ngValue]="h">{{h.name}} ({{h.emotion}})</option>
    </ng-container>
  </ng-container>
</select>

NO <span>

Attribute directives
<p myHighlight>Highlight me!</p>
import { Directive, ElementRef, Input } from '@angular/core';
@Directive({ selector: '[myHighlight]' })
export class HighlightDirective {
    constructor(el: ElementRef) {
       el.nativeElement.style.backgroundColor = 'yellow';
    }
}
Attribute directives
<p [myHighlight]="color">Highlight me!</p>
import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
  selector: '[myHighlight]'
})
export class HighlightDirective {

  constructor(private el: ElementRef) { }

  @Input('myHighlight') highlightColor: string;

  @HostListener('mouseenter') onMouseEnter() {
    this.highlight(this.highlightColor || 'red');
  }

  @HostListener('mouseleave') onMouseLeave() {
    this.highlight(null);
  }

  private highlight(color: string) {
    this.el.nativeElement.style.backgroundColor = color;
  }
}

Built in Attribute directives

  • NgClass - add and remove a set of CSS classes
  • NgStyle - add and remove a set of HTML styles
  • NgModel - two-way data binding to an HTML form element
<!-- toggle the "special" class on/off with a property -->
<div [class.special]="isSpecial">The class binding is special</div>
<div [style.font-size]="isSpecial ? 'x-large' : 'smaller'" >
  This div is x-large or smaller.
</div>

NgClass

currentClasses: {};
setCurrentClasses() {
  // CSS classes: added/removed per current state of component properties
  this.currentClasses =  {
    saveable: this.canSave,
    modified: !this.isUnchanged,
    special:  this.isSpecial
  };
}
<div [ngClass]="currentClasses">This div is initially saveable, unchanged, and special</div>

NgStyle

currentStyles: {};
setCurrentStyles() {
  // CSS styles: set per current state of component properties
  this.currentStyles = {
    'font-style':  this.canSave      ? 'italic' : 'normal',
    'font-weight': !this.isUnchanged ? 'bold'   : 'normal',
    'font-size':   this.isSpecial    ? '24px'   : '12px'
  };
}
<div [ngStyle]="currentStyles">
  This div is initially italic, normal weight, and extra large (24px).
</div>

NgModel

<input [(ngModel)]="currentHero.name">
<input [value]="currentHero.name"
       (input)="currentHero.name=$event.target.value" >

NgModel

import { NgModule } from '@angular/core';
import { BrowserModule }  from '@angular/platform-browser';
import { FormsModule } from '@angular/forms'; // <--- JavaScript import from Angular

/* Other imports */

@NgModule({
  imports: [
    BrowserModule,
    FormsModule  // <--- import into the NgModule
  ],
  /* Other module metadata */
})
export class AppModule { }
Custom Attribute directives
<p myFavorite>Text!</p>
import { Directive, HostBinding } from '@angular/core';
@Directive({
    selector: '[myFavorite]'
})
export class FavoriteDirective {
    @HostBinding('class.is-favorite') isFavorite = true;
}
Using directive values
<p [myFavorite]="item.favorite">Text!</p>
import { Directive, HostBinding, Input } from '@angular/core';
@Directive({
    selector: '[myFavorite]'
})
export class FavoriteDirective {
    @HostBinding('class.is-favorite') isFavorite = true;
    @Input() set myFavorite(value) {
        this.isFavorite = value;
    }
}
Working with events in directives
<p [myFavorite]="item.favorite">Text!</p>
import { Directive, HostBinding, Input, HostListener } from '@angular/core';
@Directive({
    selector: '[myFavorite]'
})
export class FavoriteDirective {
    @HostBinding('class.is-favorite') isFavorite = true;
    @HostBinding('class.is-favorite-hovering') hover = false;
    @HostListener('mouseenter') onMouseEnter {
        this.hover = true;
    }
    @HostListener('mouseleave') onMouseLeave {
        this.hover = false;
    }

    @Input() set myFavorite(value) {
        this.isFavorite = value;
    }
}

Pipes built in

<p>The hero's birthday is {{ birthday | date:"MM/dd/yy" }} </p>

The chained hero's birthday is
{{  birthday | date:'fullDate' | uppercase}}

Pipes built in

Pipes custom
import { Pipe, PipeTransform } from '@angular/core';
/*
 * Raise the value exponentially
 * Takes an exponent argument that defaults to 1.
 * Usage:
 *   value | exponentialStrength:exponent
 * Example:
 *   {{ 2 |  exponentialStrength:10}}
 *   formats to: 1024
*/
@Pipe({name: 'exponentialStrength'})
export class ExponentialStrengthPipe implements PipeTransform {
  transform(value: number, exponent: string): number {
    let exp = parseFloat(exponent);
    return Math.pow(value, isNaN(exp) ? 1 : exp);
  }
}
Made with Slides.com