Angular Constructor vs ngOnInit

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

📖
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

Constructor called

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

undefined

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

John

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():

📖
Best Practices:
  • 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?
Ans: Used for dependency injection and class initialization.
Q 2: What is ngOnInit?
Ans: Lifecycle hook executed after component initialization.
Q 3: Where should API calls be placed?
Ans: Inside ngOnInit.
Q 4: Can logic be written in constructor?
Ans: Only basic initialization logic.
Q 5: Why avoid heavy logic in constructor?
Ans: Because component inputs are not yet initialized.

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:






Related Angular Tutorials