The main difference between constructor and ngOnInit is that ngOnInit is lifecycle hook and runs after constructor. Component interpolated template and input initial values aren't available in constructor, but they are available in ngOnInit.
The practical difference is how ngOnInit affects how the code is structured. Most initialization code can be moved to ngOnInit - as long as this doesn't create race conditions.
Constructor antipattern
A substantial amount of initialization code makes constructor method hard to extend, read and test.
A usual recipe for separating initialization logic from class constructor is to move it to another method like init:
class Some {
constructor() {
this.init();
}
init() {...}
}
ngOnInit can serve this purpose in components and directives:
constructor(
public foo: Foo,
/* verbose list of dependencies */
) {
// time-sensitive initialization code
this.bar = foo.getBar();
}
ngOnInit() {
// rest of initialization code
}
Dependency injection
The primary role of class constructors in Angular is dependency injection. Constructors are also used for DI annotation in TypeScript. Almost all dependencies are assigned as properties to class instance.
Average component/directive constructor is already big enough because it can have multiline signature due to dependencies, putting unnecessary intialization logic to constructor body contributes to the antipattern.
Asynchronous initialization
Asynchronous initialization constructor can often be considered antipattern and have smell because class instantiation finishes before asynchronous routine does, and this can create race conditions. If it's not the case, ngOnInit and other lifecycle hooks are better places for this, particularly because they can benefit from async syntax:
If there are race conditions (including the one that a component shouldn't appear on initialization error), asynchronous initialization routine should take place before component instantiation and be moved to parent component, router guard, etc.
Unit testing
ngOnInit is more flexible than a constructor and provides some benefits for unit testing that are explained in detail in this answer.
Considering that ngOnInit isn't called automatically on component compilation in unit tests, methods that are called in ngOnInit can be spied or mocked after component instantiation.
In exceptional cases ngOnInit can be entirely stubbed to provide isolation for other component units (for instance, some template logic).
Inheritance
Child classes can only augment constructors, not replace them.
Since this cannot be referred before super(), this puts restrictions on initialization precedence.
Considering that Angular component or directive uses ngOnInit for time-insensitive initialization logic, child classes can chose whether super.ngOnInit() is called and when:
The first one (constructor) is related to the class instantiation and has nothing to do with Angular2. I mean a constructor can be used on any class. You can put in it some initialization processing for the newly created instance.
The second one corresponds to a lifecycle hook of Angular2 components:
Quoted from official angular's website:
ngOnChanges is called when an input or output binding value changes
ngOnInit is called after the first ngOnChanges
So you should use ngOnInit if initialization processing relies on bindings of the component (for example component parameters defined with @Input), otherwise the constructor would be enough...
Constructor:
The constructor method on an ES6 class (or TypeScript in this case) is a feature of a class itself, rather than an Angular feature. It’s out of Angular’s control when the constructor is invoked, which means that it’s not a suitable hook to let you know when Angular has finished initialising the component. JavaScript engine calls the constructor, not Angular directly. Which is why the ngOnInit (and $onInit in AngularJS) lifecycle hook was created. Bearing this in mind, there is a suitable scenario for using the constructor. This is when we want to utilise dependency injection - essentially for “wiring up” dependencies into the component.
As the constructor is initialised by the JavaScript engine, and TypeScript allows us to tell Angular what dependencies we require to be mapped against a specific property.
ngOnInit is purely there to give us a signal that Angular has finished initialising the component.
This phase includes the first pass at Change Detection against the properties that we may bind to the component itself - such as using an @Input() decorator.
Due to this, the @Input() properties are available inside ngOnInit, however are undefined inside the constructor, by design
The above answers don't really answer this aspect of the original question: What is a lifecycle hook? It took me a while to understand what that means until I thought of it this way.
1) Say your component is a human. Humans have lives that include many stages of living, and then we expire.
2) Our human component could have the following lifecycle script: Born, Baby, Grade School, Young Adult, Mid-age Adult, Senior Adult, Dead, Disposed of.
3) Say you want to have a function to create children. To keep this from getting complicated, and rather humorous, you want your function to only be called during the Young Adult stage of the human component life. So you develop a component that is only active when the parent component is in the Young Adult stage. Hooks help you do that by signaling that stage of life and letting your component act on it.
Fun stuff. If you let your imagination go to actually coding something like this it gets complicated, and funny.
The constructor is a default method runs when component is being constructed.
The constructor is a typescript feature and it is used only for a class instantiations and nothing to do with Angular 2.
The constructor called first time before the ngOnInit().
Angular 2 ngOnInit:-
The ngOnInit event is an Angular 2 life-cycle event method that is called after the first ngOnChanges and the ngOnInit method is use to parameters defined with @Input otherwise the constructor is OK.
The ngOnInit is called after the constructor and ngOnInit is called after the first ngOnChanges.
The ngOnChanges is called when an input or output binding value changes.
Following diagram explains the lie cycle of Angular. From that you can get an idea about the order in which each one is called.
In the Angular life-cycles
1) Angular injector detect constructor parameter('s) and instantiate class.
2) Next angular call life-cycle
Angular Lifecycle Hooks
ngOnChanges --> Call in directive parameters binding.
ngOnInit --> Start angular rendering...
Call other method with state of angular life-cycle.
The main difference between constructor and
ngOnInit
is thatngOnInit
is lifecycle hook and runs after constructor. Component interpolated template and input initial values aren't available in constructor, but they are available inngOnInit
.The practical difference is how
ngOnInit
affects how the code is structured. Most initialization code can be moved tongOnInit
- as long as this doesn't create race conditions.Constructor antipattern
A substantial amount of initialization code makes constructor method hard to extend, read and test.
A usual recipe for separating initialization logic from class constructor is to move it to another method like
init
:ngOnInit
can serve this purpose in components and directives:Dependency injection
The primary role of class constructors in Angular is dependency injection. Constructors are also used for DI annotation in TypeScript. Almost all dependencies are assigned as properties to class instance.
Average component/directive constructor is already big enough because it can have multiline signature due to dependencies, putting unnecessary intialization logic to constructor body contributes to the antipattern.
Asynchronous initialization
Asynchronous initialization constructor can often be considered antipattern and have smell because class instantiation finishes before asynchronous routine does, and this can create race conditions. If it's not the case,
ngOnInit
and other lifecycle hooks are better places for this, particularly because they can benefit fromasync
syntax:If there are race conditions (including the one that a component shouldn't appear on initialization error), asynchronous initialization routine should take place before component instantiation and be moved to parent component, router guard, etc.
Unit testing
ngOnInit
is more flexible than a constructor and provides some benefits for unit testing that are explained in detail in this answer.Considering that
ngOnInit
isn't called automatically on component compilation in unit tests, methods that are called inngOnInit
can be spied or mocked after component instantiation.In exceptional cases
ngOnInit
can be entirely stubbed to provide isolation for other component units (for instance, some template logic).Inheritance
Child classes can only augment constructors, not replace them.
Since
this
cannot be referred beforesuper()
, this puts restrictions on initialization precedence.Considering that Angular component or directive uses
ngOnInit
for time-insensitive initialization logic, child classes can chose whethersuper.ngOnInit()
is called and when:This would be impossible to implement with constructor alone.
The first one (constructor) is related to the class instantiation and has nothing to do with Angular2. I mean a constructor can be used on any class. You can put in it some initialization processing for the newly created instance.
The second one corresponds to a lifecycle hook of Angular2 components:
Quoted from official angular's website:
So you should use
ngOnInit
if initialization processing relies on bindings of the component (for example component parameters defined with@Input
), otherwise the constructor would be enough...Constructor: The constructor method on an ES6 class (or TypeScript in this case) is a feature of a class itself, rather than an Angular feature. It’s out of Angular’s control when the constructor is invoked, which means that it’s not a suitable hook to let you know when Angular has finished initialising the component. JavaScript engine calls the constructor, not Angular directly. Which is why the ngOnInit (and $onInit in AngularJS) lifecycle hook was created. Bearing this in mind, there is a suitable scenario for using the constructor. This is when we want to utilise dependency injection - essentially for “wiring up” dependencies into the component.
As the constructor is initialised by the JavaScript engine, and TypeScript allows us to tell Angular what dependencies we require to be mapped against a specific property.
ngOnInit is purely there to give us a signal that Angular has finished initialising the component.
This phase includes the first pass at Change Detection against the properties that we may bind to the component itself - such as using an @Input() decorator.
Due to this, the @Input() properties are available inside ngOnInit, however are undefined inside the constructor, by design
The above answers don't really answer this aspect of the original question: What is a lifecycle hook? It took me a while to understand what that means until I thought of it this way.
1) Say your component is a human. Humans have lives that include many stages of living, and then we expire.
2) Our human component could have the following lifecycle script: Born, Baby, Grade School, Young Adult, Mid-age Adult, Senior Adult, Dead, Disposed of.
3) Say you want to have a function to create children. To keep this from getting complicated, and rather humorous, you want your function to only be called during the Young Adult stage of the human component life. So you develop a component that is only active when the parent component is in the Young Adult stage. Hooks help you do that by signaling that stage of life and letting your component act on it.
Fun stuff. If you let your imagination go to actually coding something like this it gets complicated, and funny.
Angular 2 Constructors:-
Angular 2 ngOnInit:-
The ngOnInit event is an Angular 2 life-cycle event method that is called after the first ngOnChanges and the ngOnInit method is use to parameters defined with @Input otherwise the constructor is OK.
The ngOnInit is called after the constructor and ngOnInit is called after the first ngOnChanges.
The ngOnChanges is called when an input or output binding value changes.
Following diagram explains the lie cycle of Angular. From that you can get an idea about the order in which each one is called.