Angular provides life cycle hook ngOnInit
by default.
Why should ngOnInit
be used, if we already have a constructor
?
Angular provides life cycle hook ngOnInit
by default.
Why should ngOnInit
be used, if we already have a constructor
?
The Constructor
is a default method of the class that is executed when the class is instantiated and ensures proper initialisation of fields in the class and its subclasses. Angular, or better Dependency Injector (DI), analyses the constructor parameters and when it creates a new instance by calling new MyClass()
it tries to find providers that match the types of the constructor parameters, resolves them and passes them to the constructor like
new MyClass(someArg);
ngOnInit
is a life cycle hook called by Angular to indicate that Angular is done creating the component.
We have to import OnInit
like this in order to use it (actually implementing OnInit
is not mandatory but considered good practice):
import { Component, OnInit } from '@angular/core';
then to make use of the method OnInit
, we have to implement the class like this:
export class App implements OnInit {
constructor() {
// Called first time before the ngOnInit()
}
ngOnInit() {
// Called after the constructor and called after the first ngOnChanges()
}
}
Implement this interface to execute custom initialization logic after your directive's data-bound properties have been initialized. ngOnInit is called right after the directive's data-bound properties have been checked for the first time, and before any of its children have been checked. It is invoked only once when the directive is instantiated.
Mostly we use ngOnInit
for all the initialization/declaration and avoid stuff to work in the constructor. The constructor should only be used to initialize class members but shouldn't do actual "work".
So you should use constructor()
to setup Dependency Injection and not much else. ngOnInit() is better place to "start" - it's where/when components' bindings are resolved.
For more information refer here:
Important to note that @Input values are not accessible in the constructor (Thanks to @tim for suggestion in comments)
tsconfig.json
file like "strict": true
, then you have to initialize the class members in the constructor
, not in ngOnit
like FormGroup
. –
Giese strictPropertyInitialization: true
, Angular strongly encourages usage of constructor
for initialization, even if this involves calling services etc.? –
Minna ngOnInit
imho is accessing data-binded members with @Input
(since they are not available earlier). So if your component does not have @Input
members you should not even need ngOnInit at all –
Lubow 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
ChildComponentView
- 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:
the constructor should only be used to inject dependencies
. –
Cockup OK, first of all ngOnInit
is part of Angular lifecycle, while constructor
is part of ES6 JavaScript class, so the major difference starts from right here!...
Look at the below chart that I created which shows the lifecycle of Angular.
In Angular2+ we use constructor
to do the DI(Dependency Injection)
for us, while in Angular 1 it was happening through calling to String method and checking which dependency was injected.
As you see in the above diagram, ngOnInit
is happening after the constructor is ready and ngOnChnages
and get fired after the component is ready for us. All initialisation can happen in this stage, a simple sample is injecting a service and initials it on init.
OK, I also share a sample code for you to look, see how we get use of ngOnInit
and constructor
in the code below:
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'my-app',
template: `<h1>App is running!</h1>
<my-app-main [data]=data></<my-app-main>`,
styles: ['h1 { font-weight: normal; }']
})
class ExampleComponent implements OnInit {
constructor(private router: Router) {} //Dependency injection in the constructor
// ngOnInit, get called after Component initialised!
ngOnInit() {
console.log('Component initialised!');
}
}
I think the best example would be using services. Let's say that I want to grab data from my server when my component gets 'Activated'. Let's say that I also want to do some additional things to the data after I get it from the server, maybe I get an error and want to log it differently.
It is really easy with ngOnInit over a constructor, it also limits how many callback layers I need to add to my application.
For Example:
export class Users implements OnInit{
user_list: Array<any>;
constructor(private _userService: UserService){
};
ngOnInit(){
this.getUsers();
};
getUsers(){
this._userService.getUsersFromService().subscribe(users => this.user_list = users);
};
}
with my constructor I could just call my _userService and populate my user_list, but maybe I want to do some extra things with it. Like make sure everything is upper_case, I am not entirely sure how my data is coming through.
So it makes it much easier to use ngOnInit.
export class Users implements OnInit{
user_list: Array<any>;
constructor(private _userService: UserService){
};
ngOnInit(){
this.getUsers();
};
getUsers(){
this._userService.getUsersFromService().subscribe(users => this.user_list = users);
this.user_list.toUpperCase();
};
}
It makes it much easier to see, and so I just call my function within my component when I initialize instead of having to dig for it somewhere else. Really it's just another tool you can use to make it easier to read and use in the future. Also I find it really bad practice to put function calls within a constructor!
getUsers
and then insert it into ngOnInit
? Is it not less code to just write it in ngOnInit? I am jsut wondering why people do it this way? Is it so that you can re-use the code if you wanted too? Thanks. –
Trickish getUsers()
some meaning. Plus, if a third line would get added to ngOnInit()
unrelated to the existing two lines, it could be confusing to future maintainers. –
Goddamn constructor
? –
Gonion constructor(private _userService: UserService){ this.getUsers(); };
–
Kazantzakis I will just add one important thing that was skipped in the explanations above and explains when you MUST use ngOnInit
.
If you are doing any manipulation of the component's DOM via e.g. ViewChildren, ContentChildren or ElementRef, your native elements will not be available during the constructor phase.
However, since ngOnInit
happens once the component has been created and the checks (ngOnChanges
) have been called you can access the DOM at this point.
export class App implements OnInit, AfterViewInit, AfterContentInit {
@Input() myInput: string;
@ViewChild() myTemplate: TemplateRef<any>;
@ContentChild(ChildComponent) myComponent: ChildComponent;
constructor(private elementRef: ElementRef) {
// this.elementRef.nativeElement is undefined here
// this.myInput is undefined here
// this.myTemplate is undefined here
// this.myComponent is undefine here
}
ngOnInit() {
// this.elementRef.nativeElement can be used from here on
// value of this.myInput is passed from parent scope
// this.myTemplate and this.myComponent are still undefined
}
ngAfterContentInit() {
// this.myComponent now gets projected in and can be accessed
// this.myTemplate is still undefined
}
ngAfterViewInit() {
// this.myTemplate can be used now as well
}
}
@ViewChildren
in particular, you need to use the ngAfterViewInit
method. See here: #46315234 –
Oversight elementRef
changed? I've tested and this.elementRef.nativeElement
is not undefined in constructor. –
Draconian 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 changesngOnInit
is called after the firstngOnChanges
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...
Short and simple answer would be,
Constructor
: constructor
is a default method
runs (by default) when component is being constructed. When you create an instance
of a class that time also constructor(default method)
would be called. So in other words, when the component is being constructed or/and an instance is created constructor(default method)
is called and relevant code is written within is called. Basically and generally in Angular2
, it used to inject things like services
when the component is being constructed for further use.
OnInit
: ngOnInit is component's life cycle hook which runs first after constructor(default method)
when the component is being initialized.
So, Your constructor will be called first and Oninit will be called later after constructor method.
boot.ts
import {Cmomponent, OnInit} from 'angular2/core';
import {ExternalService} from '../externalService';
export class app implements OnInit{
constructor(myService:ExternalService)
{
this.myService=myService;
}
ngOnInit(){
// this.myService.someMethod()
}
}
Resources: LifeCycle hook
You can check this small demo which shows an implementation of both things.
new MyClass()
is executed. I think it's misleading to say constructors are about components, they are about classes and initializing instances of these classes. A component just happens to be such a class. Otherwise I think it's a good answer. –
Unnumbered constructor
would be called. But this answer has been written in angular2 context. To know the best answer you must be knowing OOPs basics. Still I'll update answer. –
Solo 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.
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
}
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 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:
constructor(
public foo: Foo,
public errorHandler: ErrorHandler
) {}
async ngOnInit() {
try {
await this.foo.getBar();
await this.foo.getBazThatDependsOnBar();
} catch (err) {
this.errorHandler.handleError(err);
}
}
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.
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).
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:
ngOnInit() {
this.someMethod();
super.ngOnInit();
}
This would be impossible to implement with constructor alone.
Like a lot of other languages, you can initialize variables at the class level, the constructor, or a method. It is up to the developer to decide what is best in their particular case. But below are a list of best practices when it comes to deciding.
Usually, you will declare all your variables here that will be used in the rest of you component. You can initialize them if the value doesn't depend on anything else, or use const keyword to create constants if they will not change.
export class TestClass{
let varA: string = "hello";
}
Normally it's best practice to not do anything in the constructor and just use it for classes that will be injected. Most of the time your constructor should look like this:
constructor(private http: Http, private customService: CustomService) {}
this will automatically create the class level variables, so you will have access to customService.myMethod()
without having to do it manually.
NgOnit is a lifecycle hook provided by the Angular 2 framework. Your component must implement OnInit
in order to use it. This lifecycle hook gets called after the constructor is called and all the variables are initialized. The bulk of your initialization should go here. You will have the certainty that Angular has initialized your component correctly and you can start doing any logic you need in OnInit
versus doing things when your component hasn't finished loading properly.
Here is an image detailing the order of what gets called:
https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html
If you are using Angular 2 framework and need to interact with certain lifecycle events, use the methods provided by the framework for this to avoid problems.
To test this, I wrote this code, borrowing from the NativeScript Tutorial:
user.ts
export class User {
email: string;
password: string;
lastLogin: Date;
constructor(msg:string) {
this.email = "";
this.password = "";
this.lastLogin = new Date();
console.log("*** User class constructor " + msg + " ***");
}
Login() {
}
}
login.component.ts
import {Component} from "@angular/core";
import {User} from "./../../shared/user/user"
@Component({
selector: "login-component",
templateUrl: "pages/login/login.html",
styleUrls: ["pages/login/login-common.css", "pages/login/login.css"]
})
export class LoginComponent {
user: User = new User("property"); // ONE
isLoggingIn:boolean;
constructor() {
this.user = new User("constructor"); // TWO
console.log("*** Login Component Constructor ***");
}
ngOnInit() {
this.user = new User("ngOnInit"); // THREE
this.user.Login();
this.isLoggingIn = true;
console.log("*** Login Component ngOnInit ***");
}
submit() {
alert("You’re using: " + this.user.email + " " + this.user.lastLogin);
}
toggleDisplay() {
this.isLoggingIn = !this.isLoggingIn;
}
}
Console output
JS: *** User class constructor property ***
JS: *** User class constructor constructor ***
JS: *** Login Component Constructor ***
JS: *** User class constructor ngOnInit ***
JS: *** Login Component ngOnInit ***
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 method in JavaScript and is considered as a feature of the class in es6 .When the class is instantiated it immediately runs the constructor whether it is used in Angular framework or not.So it is called by JavaScript engine and Angular has no control on that.
import {Component} from '@angular/core';
@Component({})
class CONSTRUCTORTEST {
//This is called by Javascript not the Angular.
constructor(){
console.log("view constructor initialised");
}
}
The "ConstructorTest" class is instantiated below;So it internally calls the constructor(All these happens by JavaScript(es6) no Angular).
new CONSTRUCTORTEST();
That is why there is ngOnInit lifecycle hook in Angular.ngOnInit renders when Angular has finished initialising the component.
import {Component} from '@angular/core';
@Component({})
class NGONINITTEST implements onInit{
constructor(){}
//ngOnInit calls by Angular
ngOnInit(){
console.log("Testing ngOnInit");
}
}
First we instantiate the class as below which happen to immediate runs of constructor method.
let instance = new NGONINITTEST();
ngOnInit is called by Angular when necessary as below:
instance.ngOnInit();
But you may ask why we are using constructor in Angular?
The answer is dependencies injections.As it is mentioned before, constructor calls by JavaScript engine immediately when the class is instantiated (before calling ngOnInit by Angular), so typescript helps us to get the type of the dependencies are defined in the constructor and finally tells Angular what type of dependencies we want to use in that specific component.
constructor() is the default method in the Component life cycle and is used for dependency injection. Constructor is a Typescript Feature.
ngOnInit() is called after the constructor and ngOnInit is called after the first ngOnChanges.
i.e.:
Constructor() --> ngOnChanges() --> ngOnInit()
as mentioned above ngOnChanges()
is called when an input or output binding value changes.
Two things to observe here:
Both have different usability.
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
Constructor is the first to execute, and it happens sometimes when @input data is null! so we use Constructor to inject services and ngOnInit happens after. Example for constructor:
constructor(translate: TranslateService, private oauthService: OAuthService) {
translate.setDefaultLang('En');
translate.use('En');}
Example for ngOnInit:
ngOnInit() {
this.items = [
{ label: 'A', icon: 'fa fa-home', routerLink: ['/'] },
{ label: 'B', icon: 'fa fa-home', routerLink: ['/'] }]
}
I think that ngOnInit is like InitialComponents() in winForm .
Both methods have different goals/responsibilities. The task of the constructor (which is a language supported feature) is to make sure that the representation invariant holds. Otherwise stated to make sure that the instance is valid by giving correct values to the members. It is up to the developer to decide what 'correct' means.
The task of the onInit() method (which is an angular concept) is to allow method invocations on a correct object (representation invariant). Each method should in turn make sure that the representation invariant holds when the method terminates.
The constructor should be used to create 'correct' objects, the onInit method gives you the opportunity to invoke method calls at a well defined instance.
The Constructor is executed when the class is instantiated. It has nothing do with the angular. It is the feature of Javascript and Angular does not have the control over it
The ngOnInit is Angular specific and is called when the Angular has initialized the component with all its input properties
The @Input properties are available under the ngOnInit lifecycle hook. This will help you to do some initialization stuff like getting data from the back-end server etc to display in the view
@Input properties are shows up as undefined inside the constructor
constructor()
is used to do dependency injection.
ngOnInit()
, ngOnChanges()
and ngOnDestroy()
etc. are lifecycle methods. ngOnChanges()
will be the first to be called, before ngOnInit()
, when the value of a bound property changes, it will NOT be called if there is no change. ngOnDestroy()
is called when the component is removed. To use it, OnDestroy
needs to be implement
ed by the class.
In the Angular life-cycles
1) Angular injector detect constructor parameter('s) and instantiate class.
2) Next angular call life-cycle
ngOnChanges --> Call in directive parameters binding.
ngOnInit --> Start angular rendering...
Call other method with state of angular life-cycle.
The constructor
is called when Angular "instanciates/constructs" the component.
The ngOnInit
method is a hook which represents the initialization part of the component lifecycle.
A good practice is to use it only for service injection:
constructor(private
service1: Service1,
service2: Service2
){};
Even if it is possible, you should not do some "work" inside.
If you want to launch some action which have to occur at component "initialization", use ngOnInit
:
ngOnInit(){
service1.someWork();
};
Moreover, actions that involve input properties, coming from a parent component, can't be done in the contructor.
They should be placed in ngOnInit
method or another hook.
It is the same for element related to the view (the DOM), for example, viewchild elements:
@Input itemFromParent: string;
@ViewChild('childView') childView;
constructor(){
console.log(itemFromParent); // KO
// childView is undefined here
};
ngOnInit(){
console.log(itemFromParent); // OK
// childView is undefined here, you can manipulate here
};
Constructor is a function executed when component (or other class) is built.
ngOnInit is a function belonging to a component life-cycle method groups and they are executed in a diffrent moment of our component (that's why name life-cycle). Here is a list of all of them:
Constructor will be executed before any life-cycle function.
Constructor
The constructor function comes with every class, constructors are not specific to Angular but are concepts derived from Object oriented designs. The constructor creates an instance of the component class.
OnInit
The ngOnInit
function is one of an Angular component’s life-cycle methods. Life cycle methods (or hooks) in Angular components allow you to run a piece of code at different stages of the life of a component.
Unlike the constructor method, ngOnInit
method comes from an Angular interface (OnInit
) that the component needs to implement in order to use this method. The ngOnInit
method is called shortly after the component is created.
Constructor
is part of ES6 also typescript is using es6 syntax and now days es7 as well so you can utilise advance feature which typescript would compile to es5/es4 (as per you define) to provide support to old browser.
While ngOnInIt
is lifecycle hook of angular. It is initialised when your component is initialised. (Consider it's state as born of any new life)
It's wise to use ngOnInIt
compare to constructor, because you have another lifecycle hook like ngOnDestory
(Consider it as death of any life). Here you can unsubscribe to any observable which is good to prevent any memory leak.
Incase any question feel free to comment on this answer.
constructor() can accept parameter and can used for dependency injection or constructor() is for adding service objects.
constructor is called before ngOnint();
ngOnInit() is for manipulating components with necessary service function calls or Generally, calls of services in the ngOnInit () and not in the constructor
I found the answer and I tried to translate it to english: This question still arised, even in technical interviews. In fact, there is a big resemblance between the two, but also there are some differences.
The constructor is part of ECMAScript. On the other hand ngOnInit() is a notion of angular.
We can call the constructors in all classes even if we do not use Angular
LifeCycle: The constructor is called before ngOnInt ()
In the constructor we can not call HTML elements. However, in ngOnInit () we can.
Generally, calls of services in the ngOnInit () and not in the constructor
Constructor is the default method provided by Typescript class, which dedicated to initializes the class members generally is used for dependencies injections services like the example code above, or timer initialization, socket connection initialization
export class AppComponent {
title = 'angular-fork-join';
constructor(private http: HttpClient) {}
ngOnInit: is a lifecycle hook called when the component is initialized provided by Angular which dedicated for example for business logic, data initialization, API calls, etc .., example code that demonstrates API call :
export class HomeComponent implements OnInit {
products = [];
constructor(private dataService: DataService) { }
ngOnInit() {
this.dataService.sendGetRequest().subscribe((data: any[])=>{
console.log(data);
this.products = data;
})
}
}
© 2022 - 2024 — McMap. All rights reserved.