Introduction
When learning Angular, one of the most common questions developers ask is: Should I use the constructor or ngOnInit() for initialization? Since both are executed when a component is created, they often appear to serve the same purpose. However, they have completely different responsibilities in Angular.
The constructor is a TypeScript feature used for dependency injection and basic object initialization, whereas ngOnInit() is an Angular lifecycle hook designed specifically for component initialization after Angular has set all input properties.
What is Constructor in Angular?
A constructor is a special method in a TypeScript (or JavaScript) class that executes automatically when an object of that class is created.
Angular primarily uses constructors for Dependency Injection (DI). When Angular creates a component, it first calls the constructor and injects the required services.
The constructor is not part of the Angular lifecycle. Instead, it is a language feature provided by TypeScript.
Key Characteristics
- Executes when the component instance is created.
- Used for dependency injection.
- Initializes simple class properties.
- Runs before Angular initializes the component.
- Does not guarantee that @Input() properties or view queries are available.
Syntax of Constructor
constructor(
private userService: UserService,
private router: Router
) {}
In this example, Angular injects the UserService and Router into the component when it creates the component instance.
What is ngOnInit()?
ngOnInit() is one of Angular’s lifecycle hooks. It belongs to the OnInit interface and is called once after Angular has initialized all data-bound properties, including @Input() values.
This makes it the ideal place for component initialization logic.
Unlike the constructor, ngOnInit() is part of Angular’s component lifecycle.
Syntax of ngOnInit()
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html'
})
export class DashboardComponent implements OnInit {
ngOnInit(): void {
console.log('Component initialized');
}
}
Angular automatically calls ngOnInit() after the component has been initialized.
Constructor vs ngOnInit()
The following table summarizes the major differences.
| Feature | Constructor | ngOnInit() |
|---|---|---|
| Type | TypeScript feature | Angular lifecycle hook |
| Purpose | Dependency Injection and object creation | Component initialization |
| Called By | JavaScript/TypeScript | Angular framework |
| Execution Time | Immediately when the component is instantiated | After Angular initializes input properties |
| Called Multiple Times | Once per instance | Once per component initialization |
| Access to @Input() | Not guaranteed | Available |
| Ideal For | Injecting services | API calls, forms, subscriptions, initialization |
Component Lifecycle Order
When Angular creates a component, the execution order is:
1. Constructor
2. ngOnChanges() (if @Input() values change)
3. ngOnInit()
4. ngDoCheck()
5. ngAfterContentInit()
6. ngAfterContentChecked()
7. ngAfterViewInit()
8. ngAfterViewChecked()
9. ngOnDestroy()
Notice that the constructor executes before Angular initializes the component.
Example 1: Using Constructor
Suppose you have a service.
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class UserService {
getUsers() {
return ['John', 'Emma', 'David'];
}
}
Now inject it into a component.
import { Component } from '@angular/core';
import { UserService } from './user.service';
@Component({
selector: 'app-users',
template: `Users
`
})
export class UsersComponent {
constructor(private userService: UserService) {
console.log('Constructor called');
}
}
Output
The constructor’s responsibility here is simply to receive the dependency.
Example 2: Using ngOnInit()
Instead of loading data inside the constructor, perform initialization inside ngOnInit().
import { Component, OnInit } from '@angular/core';
import { UserService } from './user.service';
@Component({
selector: 'app-users',
templateUrl: './users.component.html'
})
export class UsersComponent implements OnInit {
users: string[] = [];
constructor(private userService: UserService) {}
ngOnInit(): void {
this.users = this.userService.getUsers();
}
}
This approach follows Angular best practices by separating dependency injection from initialization logic.
Example 3: Why @Input() Isn’t Available in the Constructor
Consider a child component.
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-profile',
template: `{{ name }}
`
})
export class ProfileComponent {
@Input() name!: string;
constructor() {
console.log(this.name);
}
}
Output
Angular hasn’t assigned the input value yet.
Now move the code.
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'app-profile',
template: `{{ name }}
`
})
export class ProfileComponent implements OnInit {
@Input() name!: string;
ngOnInit() {
console.log(this.name);
}
}
Output
This demonstrates why ngOnInit() is the correct place for logic that depends on @Input() values.
Real-Life Example
Imagine you’re building an e-commerce website.
When the Product Details page opens, you need to:
- Inject the product service.
- Read the product ID from the route.
- Call the API.
- Display product details.
Constructor
constructor(
private productService: ProductService,
private route: ActivatedRoute
) {}
ngOnInit()
ngOnInit() {
const id = this.route.snapshot.params['id'];
this.productService.getProduct(id)
.subscribe(product => {
this.product = product;
});
}
Here:
- The constructor receives the required services.
- ngOnInit() performs the business logic and data loading.
This separation keeps the component easier to understand, test, and maintain.
When Should You Use Constructor?
Use the constructor for:
- Dependency Injection
- Initializing simple class variables
- Basic object setup
- Assigning injected services
Example:
constructor(
private authService: AuthService,
private router: Router
) {}
Avoid placing business logic or API requests here.
When Should You Use ngOnInit()?
Use ngOnInit() for:
- API calls
- Fetching user data
- Initializing forms
- Reading route parameters
- Accessing @Input() values
- Starting subscriptions
- Loading dashboard data
- Initializing charts or third-party libraries (when they don’t require the view)
This keeps initialization logic aligned with Angular’s lifecycle.
Common Mistakes
1. Calling APIs in the Constructor
Incorrect:
constructor(private userService: UserService) {
this.userService.getUsers();
}
Correct:
ngOnInit() {
this.userService.getUsers();
}
2. Accessing @Input() in the Constructor
Incorrect:
constructor() {
console.log(this.user);
}
Correct:
ngOnInit() {
console.log(this.user);
}
3. Putting Heavy Logic in the Constructor
Avoid this:
constructor() {
// Large amount of business logic
}
Constructors should remain lightweight and focused on dependency injection.
4. Forgetting to Implement OnInit
While Angular will still call a correctly named ngOnInit() method, implementing the OnInit interface is recommended because it improves readability and provides compile-time checking.
export class HomeComponent implements OnInit {
ngOnInit(): void {
}
}
Best Practices
Follow these best practices when deciding between the constructor and ngOnInit():
- Use the constructor only for dependency injection and simple initialization.
- Keep constructors lightweight and free of business logic.
- Perform API calls inside ngOnInit().
- Access @Input() values only after Angular has initialized them.
- Initialize forms, subscriptions, and application data inside ngOnInit().
- Implement the OnInit interface for better code clarity.
Conclusion
Although the constructor and ngOnInit() are both involved in a component’s creation, they have distinct responsibilities. The constructor is responsible for creating the component instance and injecting dependencies, while ngOnInit() is intended for initialization logic that depends on Angular having fully set up the component.
A simple rule to remember is:
- Use the constructor to inject services and perform minimal object setup.
- Use ngOnInit() to initialize the component, load data, make API calls, read @Input() values, and start subscriptions.
Angular Constructor vs ngOnInit – Interview Questions
Q 1: What is Constructor?
Q 2: What is ngOnInit?
Q 3: Where should API calls be placed?
Q 4: Can logic be written in constructor?
Q 5: Why avoid heavy logic in constructor?
Angular Constructor vs ngOnInit – Objective Questions (MCQs)
Q1. Constructor is mainly used for:
Q2. ngOnInit() is used for:
Q3. Constructor executes:
Q4. ngOnInit is part of:
Q5. Best place for API calls is: