What is the difference between ngOnInit and constructor?
In Angular, both the constructor and ngOnInit are lifecycle hooks that allow you to execute code when a component or directive is initialized. However, they serve different purposes and are invoked at different stages of the component lifecycle.
The constructor
The constructor is a standard TypeScript feature (and JavaScript ES6+) used for class instantiation. It's the first method that gets called when a new instance of a class is created. Its primary purpose in Angular is for dependency injection.
When Angular creates a component or directive, it first calls its constructor to set up the initial state of the class and inject any required services. You should avoid heavy logic or operations that might cause side effects within the constructor.
import { Component } from '@angular/core';
import { MyService } from './my.service';
@Component({
selector: 'app-my-component',
templateUrl: './my-component.html',
styleUrls: ['./my-component.css']
})
export class MyComponent {
constructor(private myService: MyService) {
// This is primarily for dependency injection
console.log('Constructor called!');
// myService is available here
}
}
ngOnInit
ngOnInit is an Angular-specific lifecycle hook. It is called once, after the constructor, and after Angular has initialized all data-bound properties of a directive or component. This makes it a more suitable place for initialization logic that relies on those properties.
It's commonly used for fetching initial data, setting up subscriptions, or performing any complex initialization logic that might depend on input properties (@Input()) or other data bindings. It's also the first time you can reliably access these input properties.
import { Component, OnInit, Input } from '@angular/core';
import { MyService } from './my.service';
@Component({
selector: 'app-another-component',
templateUrl: './another-component.html',
styleUrls: ['./another-component.css']
})
export class AnotherComponent implements OnInit {
@Input() itemId: string;
data: any;
constructor(private myService: MyService) {
console.log('Constructor called. itemId:', this.itemId); // itemId might be undefined
}
ngOnInit(): void {
console.log('ngOnInit called. itemId:', this.itemId); // itemId is now available
if (this.itemId) {
this.myService.getData(this.itemId).subscribe(response => {
this.data = response;
});
}
}
}
Key Differences
- Invocation Timing:
constructoris called first (JS/TS feature);ngOnInitis called after (Angular lifecycle hook). - Purpose:
constructorfor dependency injection and basic setup;ngOnInitfor initialization logic after data-bound properties are set. - Access to @Input:
@Inputproperties are not available in theconstructor, but are guaranteed to be available inngOnInit. - Framework Specific:
constructoris a standard language feature;ngOnInitis specific to Angular. - Interface:
constructordoes not implement an interface;ngOnInitrequires implementing theOnInitinterface for type safety (though not strictly enforced by runtime).
When to use which
Use the constructor primarily for injecting services or other dependencies. Keep it lightweight and avoid complex logic.
Use ngOnInit for all other initialization logic. This includes fetching data, setting up subscriptions, or any operations that rely on Angular's data-bound properties (like @Input()).