The article The essential difference between Constructor and ngOnInit in Angular explores the difference from multiple perspectives. This answer provides the most important difference explanation related to the component initialization process which also shows the different in usage.
Angular bootstrap process consists of the two major stages:
The constructor of the component is called when Angular constructs components tree. All lifecycle hooks are called as part of running change detection.
When Angular constructs components tree the root module injector is already configured so you can inject any global dependencies. Also, when Angular instantiates a child component class the injector for the parent component is also already set up so you can inject providers defined on the parent component including the parent component itself. Component constructors is the only method that is called in the context of the injector so if you need any dependency that's the only place to get those dependencies.
When Angular starts change detection the components tree is constructed and the constructors for all components in the tree have been called. Also every component's template nodes are added to the DOM. The @Input
communication mechanism is processed during change detection so you cannot expect to have the properties available in the constructor. It will be available on after ngOnInit
.
Let's see a quick example. Suppose you have the following template:
<my-app>
<child-comp [i]='prop'>
So Angular starts bootstrapping the application. As I said it first creates classes for each component. So it calls MyAppComponent
constructor. It also creates a DOM node which is the host element of the my-app
component. Then it proceeds to creating a host element for the child-comp
and calling ChildComponent
constructor. At this stage it's not really concerned with the i
input binding and any lifecycle hooks. So when this process is finished Angular ends up with the following tree of component views:
MyAppView
- MyApp component instance
- my-app host element data
ChildCompnentView
- ChildComponent component instance
- child-comp host element data
Only then runs change detection and updates bindings for the my-app
and calls ngOnInit
on the MyAppComponent class. Then it proceeds to updating the bindings for the child-comp
and calls ngOnInit
on the ChildComponent class.
You can do your initialization logic in either constructor or ngOnInit
depending on what you need available. For example the article Here is how to get ViewContainerRef before @ViewChild query is evaluated shows what type of initialization logic can be required to be performed in the constructor.
Here are some articles that will help you understand the topic better: