5. Lifecycle Hooks (Number to be updated)

Lifecycle sequence:

constructor(): ...

ngOnChanges(): Responds when Angular (re)-sets data bound input properties.Method receives a SimpleChange object of current and previous property values.

ngOnInit(): Initialize directive/component after Angular first displays data bound properties and sets directive component's input properties.

ngDoCheck(): Detect and act upon changes Angular can't or won't detect on its own.

ngAfterContentInit(): Responds after Angular projects external content into the component's view.

ngAfterContentChecked(): Responds after Angular checks the content projected into the component.

ngAfterViewInit(): Responds after Angular initializes the component's views and child views.

ngAfterViewChecked(): Responds after Angular checks the component's views and child views.

ngOnDestroy(): Cleanup just before Angular destroys the directive/component. Unsubscribe Observables and detach event handlers to avoid memory leaks.

Interfaces are optional(technically):

Good practice to implement them, same as the @Injectable decorator. Make your code more readable and maintainable.

LoggerService:

import { Injectable } from '@angular/core';

@Injectable()
export class LoggerService {
  logs: string[] = [];

  previousMessage = '';
  previousMessageCount = 1;

  log(message: string) {
    if (message === this.previousMessage) {
      // repeat message; update last log entry with count.
      this.logs[this.logs.length -1] = message + `(${this.previousMessageCount += 1}x)`;
    } else {
      // new message; log it.
      this.previousMessage = message;
      this.previousMessageCount = 1;
      this.logs.push(message);
    }
  }
  clear() { this.logs.length = 0; }

  // schedules a view refresh to ensure display catches up
  tick() { this.tick_then(() => { }); }
  tick_then(fn: () => any) { setTimeout(fn, 0); }

}

MyTechnologyComponent:

import { Component, Input} from '@angular/core';
import { OnInit, OnChanges, SimpleChanges, DoCheck, AfterContentInit, AfterContentChecked,
        AfterViewInit, AfterViewChecked, OnDestroy} from '@angular/core';

import { LoggerService } from './logger.service';

let nextId = 1;

export class MyTechnology implements OnInit {
        constructor(private logger: LoggerService) { }
        // implements OnInit ngOnInit method
        ngOnInit() { this.logIt('OnInit'); }
        logIt(message: string): void {
          this.logger.log(`#${nextId++} ${message}`);
        }
}
@Component({
  selector: 'app-my-technology',
  template: `<p>Now you see my technology: {{ name }}</p>`,
  styles: [`p {background: #ff8080; padding: 10px; }`]
})
export class MyTechnologyComponent extends MyTechnology implements OnInit, OnChanges,
                                   DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit,
                                   AfterViewChecked, OnDestroy {

                @Input() name: string;
                private verb = 'initialized';

                constructor(logger: LoggerService) {
                  super(logger);
                }

                // only called for/if there is an @input variable set by the parent.
                ngOnChanges(changes: SimpleChanges) {
                  const changesMessages: string[] = [];
                  for (const propertyName in changes) {
                    if (propertyName === 'name') {
                      const name = changes['name'].currentValue;
                      changesMessages.push(`name ${this.verb} to "${name}"`);
                    } else {
                      changesMessages.push(propertyName + ' ' + this.verb);
                    }
                  }
                  this.logIt(`OnChanges: ${changesMessages.join('; ')}`);
                  this.verb = 'changed'; // next time it will be a change
                }

                // beware called frequently!
                // called in every change detection cycle anywhere on the page
                ngDoCheck() { this.logIt(`DoCheck`); }

                ngAfterContentInit() { this.logIt(`AfterContentInit`); }

                // beware called frequently!
                // called in every change detection cycle anywhere on the page
                ngAfterContentChecked() { this.logIt(`AfterContentChecked`); }

                ngAfterViewInit() { this.logIt(`AfterViewInit`); }

                // called in every change detection cycle anywhere on the page
                ngAfterViewChecked() { this.logIt(`AfterViewChecked`); }

                ngOnDestroy() { this.logIt(`OnDestroy`); }
}

MyTechnologyHostComponent:

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

import { LoggerService } from './logger.service';

@Component({
  selector: 'app-my-technology-host',
  template: `
      <div class="host">
        <h2>My-Technology-Host</h2>
        <button class="redy" (click)="toggle()">
            {{ hasChild ? 'Destroy' : 'Create' }} MyTechnologyComponent
        </button>
        <button class="redy" (click)="updateTechnology()" [hidden]="!hasChild">Update Technology</button>
        <app-my-technology *ngIf="hasChild" [name]="technologyName"></app-my-technology>
        <h4>--- Lifecycle Hook Log ---</h4>
        <div *ngFor="let message of hookLog">{{ message }}</div>
      </div>
  `,
  styles: [`.host { background: #ff3333; color: white; } .redy { background: #4d0000; }`],
  providers: [ LoggerService ]
})
export class MyTechnologyHostComponent {

          hasChild = false;
          hookLog: string[] = [];
          technologyName = 'Angular 4';
          private logger: LoggerService;

          constructor(logger: LoggerService) {
            this.logger = logger;
            this.hookLog = logger.logs;
          }

          toggle() {
            this.hasChild = !this.hasChild;
            if (this.hasChild) {
              this.technologyName = 'Angular 4';
              this.logger.clear();
            }
            this.logger.tick();
          }
          updateTechnology() {
            this.technologyName += '*';
            this.logger.tick();
          }

}

Let's have a look at this beauty in our Chromium Web Browser. Note, My Polymer Princess is for my eyes only:

Spy Directive:

results matching ""

    No results matching ""