287

Why isn't ngOnInit() called when an Injectable class is resolved?

Code

import {Injectable, OnInit} from 'angular2/core';
import { RestApiService, RestRequest } from './rest-api.service';

@Injectable()
export class MovieDbService implements OnInit {

    constructor(private _movieDbRest: RestApiService){
        window.console.log('FROM constructor()');
    }

    ngOnInit() {
         window.console.log('FROM ngOnInit()');
    }

}

Console Output

FROM constructor()
Zameer Ansari
  • 28,977
  • 24
  • 140
  • 219
Levi Fuller
  • 13,631
  • 4
  • 38
  • 44

5 Answers5

425

Lifecycle hooks, like OnInit() work with Directives and Components. They do not work with other types, like a service in your case. From docs:

A Component has a lifecycle managed by Angular itself. Angular creates it, renders it, creates and renders its children, checks it when its data-bound properties change and destroy it before removing it from the DOM.

Directive and component instances have a lifecycle as Angular creates, updates, and destroys them.

Community
  • 1
  • 1
Sasxa
  • 40,334
  • 16
  • 88
  • 102
  • 49
    So simply move my `ngOnInit` logic to the constructor for `Injectable` classes? I just remembered reading that you should keep any logic out of the constructor for whatever reason. – Levi Fuller Jan 31 '16 at 06:00
  • 59
    @LeviFuller Yea, for services you can do initialization in the constructor, or better make init method and call it from the constructor (in case you need to reset a service later). – Sasxa Jan 31 '16 at 06:03
  • Perfect. Thanks mate. I assume the reason is because Components will only be instantiated once, therefore, the constructor will only be called the first time, while ngOnInit will be called each time the component is rendered. Does that seem correct? – Levi Fuller Jan 31 '16 at 06:06
  • 11
    Not exactly, [OnInit](https://angular.io/docs/ts/latest/api/core/OnInit-interface.html) has to do with binding. You use it when you want to wait for input values to be resolved, as they are not available in the constructor. Constructor can be called multiple times. For example, when you change route and load different components they get "constructed" and destroyed each time... – Sasxa Jan 31 '16 at 06:10
  • 7
    It's also worth noting here that Sevices _can_ be instantiated multiple times, depending on where you include them in `providers` arrays. If you want a singleton service, put it in your main module's `providers`, and if you want per-component services add them to the component directly. – Askdesigners Apr 05 '17 at 12:38
  • 6
    This is not entirely incorrect, as @SBD580 points in his answer, `ngOnDestroy` is called for injected services – shusson Apr 12 '17 at 07:58
  • 1
    `ngOnDestroy` for providers is a special case dealing with eager loading [#13960](https://github.com/angular/angular/issues/13960). It's not documented so I didn't update the answer. In my opinion, it should've been called something else, hooks are confusing enough for beginners (; – Sasxa Apr 12 '17 at 09:43
  • 1
    So then the best practice of not initializing stuff in the constructor doesn't apply here and we should use the constructor to initialize variables? – Thom Jan 24 '18 at 15:16
  • In a similar situation, I had to use a static variable in angular6, instance variable didn't work. – Manohar Reddy Poreddy Nov 29 '18 at 15:43
  • 1
    @Thom - you can add a regular public init() method on your service, import the serivce and call it from your AppComponent's ngOnInit() – Joe Hanink Oct 28 '19 at 18:25
  • I want to "await" a function call that happens when my Angular service starts up... none of these comments allow me to do this... – Jim Nov 06 '20 at 17:27
  • Constructor doesn't work for async functions, however, you can put it in the `ngOnInit()` call of the component using the service. May or may not work depending on where all you use the service and how but does allow onInit timing. – coppereyecat Sep 23 '21 at 16:52
  • This should be in the documentation! I was struggling with why my onInit logic does not fire for a full day because of this... – Viktor Sep 05 '22 at 06:37
65

I don't know about all the lifecycle hooks, but as for destruction, ngOnDestroy actually get called on Injectable when it's provider is destroyed (for example an Injectable supplied by a component).

From the docs :

Lifecycle hook that is called when a directive, pipe or service is destroyed.

Just in case anyone is interested in destruction check this question:

Abdullah Khan
  • 12,010
  • 6
  • 65
  • 78
SBD580
  • 691
  • 5
  • 3
  • 9
    such a shame `ngOnInit` isn't called :-( I really wanted to do some transparent delayed initialization magic. If `ngOnDestroy` can be called I don't see why init can't – Simon_Weaver Mar 11 '19 at 08:55
11

Adding to answer by @Sasxa,

In Injectables you can use class normally that is putting initial code in constructor instead of using ngOnInit(), it works fine.

Chanel
  • 902
  • 12
  • 18
5

Note: this answer applies only to Angular components and directives, NOT services.

I had this same issue when ngOnInit (and other lifecycle hooks) were not firing for my components, and most searches led me here.

The issue is that I was using the arrow function syntax (=>) like this:

class MyComponent implements OnInit {
    // Bad: do not use arrow function
    public ngOnInit = () => {
        console.log("ngOnInit");
    }
}

Apparently that does not work in Angular 6. Using non-arrow function syntax fixes the issue:

class MyComponent implements OnInit {
    public ngOnInit() {
        console.log("ngOnInit");
    }
}
AJ Richardson
  • 6,610
  • 1
  • 49
  • 59
  • 3
    Injectable classes are Services, not Components. OP asks about a Service. Although your answer may be correct from a language POV, it doesn't answer this question. You should delete it. – Andrew Philips May 16 '19 at 06:41
  • 2
    @AndrewPhilips while my use case is slightly different from the OP's, a google search for "ngOnInit not called" leads people here. My goal with this answer is not to help the OP, but to help any of the other 70,000+ viewers who might have has similar issues with `ngOnInit`. – AJ Richardson May 16 '19 at 11:27
  • 1
    Fair enough. I believe I’ve seen SO Q&A in which an author asks and then answers their own question. As a new Angular programmer, your answer would have confused me two weeks ago. Both from an SO and NG perspective, I think your answer is worthy of its own Question, so not deleted but “recategorized”. Who knows? Perhaps it might reach an even wider audience. Cheers. – Andrew Philips May 16 '19 at 12:33
  • 1
    Makes sense - I edited my answer to make it clear that this is not for services. – AJ Richardson May 27 '19 at 14:32
4

I had to call a function once my dataService was initialized, instead, I called it inside the constructor, that worked for me.