Both the constructor and ngOnInit() run when a component is created, but they have different responsibilities.
Simple difference:
Constructor → TypeScript/JavaScript class creation and dependency injection.ngOnInit()→ Angular component initialization after Angular has set initial input values.
1. What is a Constructor?
A constructor is a TypeScript class feature, not an Angular lifecycle hook.
It executes when an instance of the class is created.
constructor() {
console.log('Constructor');
}
In Angular, constructors are traditionally used to receive dependencies through Dependency Injection:
constructor(private userService: UserService) {
}
Angular creates the component and supplies the required service.
2. What is ngOnInit()?
ngOnInit() is an Angular lifecycle hook.
It runs once after Angular has initialized the component's input properties.
ngOnInit(): void {
console.log('ngOnInit');
}
It is commonly used for component initialization logic.
Full Simple Sample Program
This example makes the difference especially clear using @Input().
app.ts — Parent
import { Component } from '@angular/core';
import { User } from './user';
@Component({
selector: 'app-root',
standalone: true,
imports: [User],
template: `
<h1>Parent Component</h1>
<app-user [name]="name"></app-user>
`
})
export class App {
name = 'Syed';
}
user.ts — Child
import {
Component,
Input,
OnInit
} from '@angular/core';
@Component({
selector: 'app-user',
standalone: true,
template: `
<h2>User Component</h2>
<p>Name: {{ name }}</p>
`
})
export class User implements OnInit {
@Input()
name = '';
constructor() {
console.log('Constructor');
console.log(
'Name in Constructor:',
this.name
);
}
ngOnInit(): void {
console.log('ngOnInit');
console.log(
'Name in ngOnInit:',
this.name
);
}
}
Output
The parent passes:
<app-user [name]="name"></app-user>
where:
name = 'Syed';
You will conceptually see:
Constructor
Name in Constructor:
ngOnInit
Name in ngOnInit: Syed
This demonstrates the key difference.
Why Is name Empty in the Constructor?
Initially, the child declares:
@Input()
name = '';
Angular first creates the component instance.
That causes the constructor to execute:
Create User object
↓
constructor()
At that point, Angular has not yet completed assigning the parent's input value.
Then Angular assigns:
Parent
name = "Syed"
↓
@Input()
↓
Child
name = "Syed"
After the initial inputs are established, Angular calls:
ngOnInit()
Therefore:
constructor
↓
name = ""
Angular sets @Input
↓
name = "Syed"
ngOnInit
↓
name = "Syed"
This is one of the most important reasons not to rely on @Input() values in the constructor.
Execution Order
When a component with inputs is created, think:
Component class instantiated
↓
constructor()
↓
Angular sets @Input values
↓
ngOnChanges()
↓
ngOnInit()
↓
ngDoCheck()
↓
...
So:
constructor()
↓
ngOnChanges()
↓
ngOnInit()
What Should We Put in Constructor?
The constructor should generally stay lightweight.
A classic use is dependency injection:
constructor(
private userService: UserService
) {
}
For example:
export class User {
constructor(
private userService: UserService
) {
}
}
Modern Angular can also inject dependencies using:
private userService = inject(UserService);
so constructor injection is no longer the only DI syntax.
What Should We Put in ngOnInit()?
Put component initialization logic that should happen after Angular has initialized the component's inputs.
For example:
ngOnInit(): void {
console.log(this.name);
this.loadUsers();
}
A common pattern is:
constructor(
private userService: UserService
) {
}
ngOnInit(): void {
this.loadUsers();
}
Think:
constructor
↓
Get dependencies
ngOnInit
↓
Use dependencies for
component initialization
Service Example
Consider:
constructor(
private productService: ProductService
) {
}
The constructor receives the service.
Then:
ngOnInit(): void {
this.productService
.getProducts()
.subscribe(...);
}
performs initialization.
Conceptually:
constructor
↓
"Give me ProductService"
↓
Dependency available
ngOnInit
↓
"Initialize my component"
↓
Load products
Constructor vs ngOnInit()
| Constructor | ngOnInit() |
|---|---|
| TypeScript/JavaScript class mechanism | Angular lifecycle hook |
| Runs when class instance is created | Runs after Angular initializes inputs |
Runs before ngOnInit() |
Runs after constructor and initial ngOnChanges() |
| Commonly used for DI | Commonly used for initialization |
Don't rely on @Input() values |
Initial @Input() values are available |
| Keep lightweight | Appropriate for component startup logic |
| Runs once per class instance | Runs once per component instance |
Important: API Call — Constructor or ngOnInit()?
You might technically write:
constructor(
private service: ProductService
) {
this.service.getProducts().subscribe();
}
But for a component, initialization work is generally clearer in:
constructor(
private service: ProductService
) {
}
ngOnInit(): void {
this.service
.getProducts()
.subscribe();
}
This separates responsibilities:
Constructor
↓
Dependency setup
ngOnInit
↓
Component initialization
It also matters when initialization depends on an input:
@Input()
categoryId = '';
ngOnInit(): void {
this.productService
.getProducts(this.categoryId)
.subscribe();
}
The initial categoryId has already been assigned by Angular by this point.
Advantages of Constructor
- Automatically runs when the class is instantiated.
- Natural place for constructor-based dependency injection.
- Good for simple class-level setup.
- Standard TypeScript/JavaScript class behavior.
Advantages of ngOnInit()
- Part of Angular's component lifecycle.
- Runs after initial inputs have been set.
- Good place for component initialization.
- Runs once per component instance.
- Keeps initialization logic separate from object construction.
Disadvantages / Considerations
Constructor
Avoid putting heavy initialization work in the constructor.
Especially avoid relying on:
@Input()
because Angular may not have assigned those values yet.
ngOnInit()
It only runs once.
Therefore, if an @Input() changes later:
Syed
↓
Mohamed
ngOnInit() does not run again.
For responding to later input changes, use mechanisms such as:
ngOnChanges()
when appropriate.
Key Points
The easiest way to remember is:
constructor()
↓
CREATE CLASS
+
INJECT DEPENDENCIES
ngOnInit()
↓
INITIALIZE COMPONENT
And for @Input():
constructor()
↓
@Input may not have parent value yet
Angular sets @Input
↓
ngOnChanges()
↓
ngOnInit()
↓
Initial @Input value available
Interview Questions and Answers
1. What is the difference between constructor and ngOnInit()?
A constructor is a TypeScript/JavaScript class mechanism that runs when an object is instantiated and is commonly used for dependency injection.
ngOnInit() is an Angular lifecycle hook that runs once after Angular initializes the component's input properties.
2. Which runs first?
The constructor runs first.
constructor
↓
ngOnChanges (when applicable)
↓
ngOnInit
3. Can we access @Input() in the constructor?
The property itself exists, but you should not rely on the parent-provided input value being initialized there.
Use ngOnInit() for logic that requires the initial input value, or ngOnChanges() when you need to react specifically to input changes.
4. Where should dependency injection happen?
Traditionally:
constructor(
private service: UserService
) {}
Modern Angular also supports:
private service = inject(UserService);
5. Where should component initialization logic go?
Generally:
ngOnInit()
especially when that initialization depends on Angular-bound inputs.
6. Does ngOnInit() run when an @Input() changes later?
No. ngOnInit() runs only once per component instance. ngOnChanges() can respond to later input changes.
Interview One-Line Answer
The constructor is used to create the class instance and commonly inject dependencies, while
ngOnInit()is an Angular lifecycle hook used to initialize the component after Angular has set its initial input values.