Angular constructor versus ngOnInit blog post

Angular constructor versus ngOnInit

Todd Motto

24 Sep, 2019

Angular

5 minutes read

Let’s explore the key differences between the OnInit lifecycle hook in Angular versus the constructor that we declare via a TypeScript class. The difference between the two, or where to put particular logic, has been the source of some confusion for those getting started with Angular –

"Do I put this in the constructor?"

"What do I need OnInit for?"

"Can I use the constructor and OnInit for the same thing?"

This post was written to answer some of these questions you may be having and show you the difference between constructors and the OnInit lifecycle hook, to guide you through making your own decisions when building out your Angular apps.

To better understand the decision we would need to make, let’s understand what a constructor and lifecycle hook is.

What is a constructor?

The constructor is a method that lives on a JavaScript (ES2015/ES6) class (or a TypeScript class in this case) is a feature of a class itself – it’s not an Angular feature!

A constructor is invoked first when a class is being instantiated, which means it’s a good place to possibly put some logic.

class Pizza {
  constructor() {
    console.log('Hello world!');
  }
}

// create a new instance, constructor is 
// then invoked by the *JavaScript Engine*!
const pizza = new Pizza();

The main piece here is that the JavaScript engine calls the constructor, not Angular directly, as in this example – there is no Angular! It’s plain JavaScript.

Constructors in Angular

What about when we are using Angular? In this case, the constructor is best left for simply ‘wiring things up’, as this is where Angular resolves providers you declare in your constructor, through Dependency Injection:

import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({...})
class PizzaComponent {
  constructor(
    private route: ActivatedRoute
  ) {}
}

This will bind ActivatedRoute to the class, making it accessible as part of the component class via this.route.

The lesson here is that it’s out of Angular’s control when the constructor is invoked, so we should leave it for merely wiring up purposes instead of attempting to place any initialisation logic here – as Angular has a special lifecycle hook, OnInit, for this very reason. But before we dive too deep on OnInit, let’s understand the concept of a lifecycle hook.

What are Lifecycle Hooks in Angular?

Lifecycle hooks are just methods on an object, on a component for example, at key points in time. Some typical lifecycle hooks that ship with Angular include OnInit, OnDestroy and OnChanges. For the complete list of lifecycle hooks, check out the Lifecycle Hooks documentation page.

Want to deep-dive into Angular’s lifecycle hooks? We have an "Exploring Lifecycle Hooks" series covering them all! Start with our guide to OnInit and follow the rest of the series.

A lifecycle hook could give us key insights as to what’s happening with a component, for instance. When the component is created, the OnChanges lifecycle hook fires first. Secondly, OnInit, where we now realise our component is ready to go. If our component were to be destroyed, we’d then be able to write some code to slot into the OnDestroy lifecycle hook – to run some cleanup logic, perhaps.

With this in mind, what does the OnInit lifecycle hook give us?

OnInit Lifecycle Hook

By adding this lifecycle hook to a component, Angular has full control, unlike the constructor. Angular will invoke the OnInit lifecycle hook once it has finished setting the component up.

The way we can use this hook is via an interface, OnInit, which we simply declare via the implements keyword (this will create a contract between the class and TypeScript to ensure the method ngOnInit is present on the class):

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({...})
class PizzaComponent implements OnInit {
  constructor(
    private route: ActivatedRoute
  ) {}
  
  ngOnInit() {
    // subscribe when OnInit fires
    this.route.params.subscribe(params => {
      // now we can do something!
    });
  }
}

This approach also makes unit testing easier, as we could actually invoke the lifecycle hook ourselves. Here’s what technically happens when Angular instantiates our component and invokes ngOnInit:

const instance = new PizzaComponent();

// Angular calls this when it's ready
instance.ngOnInit();

Differences between constructor and OnInit

ngOnInit is purely there to give us a signal that Angular has finished initialising the component, and we’re ready to roll. This initialisation phase includes the first pass at Change Detection, which means any @Input() properties are available inside ngOnInit, however are undefined inside the constructor, by design.

The differences are subtle, yet important. Now we’ve fully explored the constructor role, you’re now primed to make the right decision with OnInit! Using OnInit gives us a guarantee that bindings are readily available and we can use them to the fullest.

To learn more techniques, best practices and real-world expert knowledge I’d highly recommend checking out my Angular courses – they will guide you through your journey to mastering Angular to the fullest!

It’s also important not to overload your constructor with initialisation logic, with this in mind and benefits we see unit testing – we’re onto a winner.

About the author

Todd Motto profile picture

Todd Motto

GDE Google Developer Expert

Todd is the Founder of Ultimate Courses. With a passion for Angular, TypeScript and JavaScript, Todd leads the online courses creation and has written hundreds of articles on front-end web development and beyond. He specialises in breaking down complex topics and understands the critical mission of learning new technology fast, comprehensively and the right way.

Leave a Reply

Love the post? Share it!

Lots of time and effort go into all our blogs, resources and demos,
we'd love it if you'd spare a moment to share them!

Explore our Angular courses

Get started today and join over 60,000 developers.