Search code examples
angularlifecycle

How to get the correct lifecycle hook in Angular 7


I am trying to get a timestamp using performance.now() when Angular has loaded the view and shows the components. In the official docs there is an array of different possibilities listed:

  • ngOnChanges
  • ngOnInit
  • ngDoCheck
  • ngAfterContentInit
  • ngAfterContentChecked
  • ngAfterViewInit
  • ngAfterViewChecked

See: https://angular.io/guide/lifecycle-hooks

I made a project using ng new that is very simple and has the following content:

testing.component.html

<p>
  "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
</p>

app.component.html

<app-testing *ngFor="let i of Arr(num).fill(1)"></app-testing>

app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

  Arr = Array; //Array type captured in a variable
  num:number = 10000;

  timeBefore : number = 0;
  timeAfter : number = 0;

  ngOnChanges(){
    console.log('ngOnChanges');
  }

  ngOnInit(){
    console.log('ngOnInit');
    this.timeBefore = performance.now();
  }

  ngDoCheck(){
    console.log('ngDoCheck');
  }

  ngAfterContentInit(){
    console.log('ngAfterContentInit');
  }

  ngAfterContentChecked(){
    console.log('ngAfterContentChecked');
  }

  ngAfterViewInit(){
    console.log('ngAfterViewInit');
  }

  ngAfterViewChecked(){
    console.log('ngAfterViewChecked');

    this.timeAfter = performance.now();

    console.log(this.timeAfter - this.timeBefore + " took miliseconds!");
  }
}

I made a video that demonstrates my problem:

https://youtu.be/xMk01kMwXl8

In the video you can see that I log all the hooks, and the last one that is logged is ngAfterViewChecked. But when that is logged, the components have not yet been displayed. I need to run some code (like getting a timestamp) when the components are actually shown to the user, so that I can compare the difference to when the page started loading.

Is this possible and if so how do I do it?


Solution

  • What you see is not the AppComponent have not be rendered, but because it's child component is still running their life cycle hook.

    • The way Angular generate these components is known as Unidirectional which mean it finish life cycle hook and update DOM of the whole component tree one after one starting at the root component.

    • On each component, Angular is going to run the change detection mechanism that is associated with that component and will determine if the component needs to be render/re-rendered, if it does need to be rerender, then it will update the View of that component also update the DOM.

    • This process is done from the root of the component tree down until
      the leaf components of the application

    So what you seen is that the AppComponent had already finished it lifecycle hooks and be rendered, but it's child component is still running their. And the ngAfterViewInit() is the method that will gurantee be run after the component is fisnished intialize as View.