constructor vs ngOnInit in Angular

This post is 4 years old. (Or older!) Code samples may not work, screenshots may be missing and links could be broken. Although some of the content may be relevant please take it with a pinch of salt.

If you have seen a component created using Angular2+, you have probably also seen the usage of the constructor() and ngOnInit() methods. In this article we'll investigate the differences between them and see why both of them exist.

Example code

Here's how a brand new generated component via the Angular CLI looks like (if you don't already know, you can create a new component via this command: ng generate component):

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

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

ngOnInit() {}
}

The constructor

Let's start with the constructor first. The constructor() is not related to Angular as TypeScript (and the ECMAScript 2015 version of JavaScript) can work with classes and therefore they have access to the constructor method.

This also means that the constructor is invoked by the JavaScript engine and not by Angular.

ngOnInit

ngOnInit() is one of the lifecycle hooks that Angular makes available to developers. A lifecycle hook - as its name suggests - allows us to access the various lifecycle stages of the component. So ngOnInit is a piece of code that Angular invokes when the component has been created.

When to use constructor and ngOnInit?

Based on the above two explanations we can now see how these two methods are different, and they each have different use cases.

Remember this simple rule of thumb: use the constructor() for applying dependency injection - i.e. to bring in dependencies that you wish to use in the component.

import { HttpClient } from '@angular/common/http';
// ...
constructor(private http: HttpClient) { }

ngOnInit is called by Angular when it has created the component, loaded all its dependencies, has placed the component to the DOM and processed all the input bindings. This means that by design the input values are accessible inside ngOnInit and not in the constructor:

// given that the component is called via: <app-my-component [user]="user"></app-my-component>
export class MyComponentComponent implements OnInit {
@Input()
user: any;
constructor() {
console.log(this.user); // undefined
}

ngOnInit() {
console.log(this.user); // { username: "John", age: 33 }
}
}