Angular Lifecycle Hook In The Wrong Context

ID

javascript.angular_lifecycle_context

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Dead Code

Language

JavaScript

Tags

angular, framework, reliability, unused-code

Description

Reports an Angular change-detection lifecycle hook declared on a class Angular never calls it on — a service, a pipe or a module:

@Injectable({ providedIn: "root" })
export class DataService {
  ngOnInit() {                 // FLAW — never runs
    this.load();
  }

  ngOnDestroy() {              // fine: the injector calls this one
    this.close();
  }
}

The seven hooks reported are ngOnInit, ngOnChanges, ngDoCheck, ngAfterContentInit, ngAfterContentChecked, ngAfterViewInit and ngAfterViewChecked, on a class decorated with @Injectable, @Pipe or @NgModule.

Rationale

Those seven hooks belong to the change-detection cycle, and change detection visits only what appears in a view: components and directives. A class the injector builds as a provider, a transformation or a module never enters that cycle.

The failure is silent. Nothing throws, nothing warns, the initialisation simply never happens — and the bug surfaces much later, somewhere else, as a value that was supposed to be loaded and is not. The method reads as live setup to every reviewer.

ngOnDestroy is the exception and is not reported: the injector calls it when the providing scope is torn down, which is the documented way for a service or a pipe to release a subscription.

Remediation

Decide which of the two the class is:

  • If the initialisation belongs to the service, run it from the constructor, or from an explicit method the consumer calls:

@Injectable({ providedIn: "root" })
export class DataService {
  constructor() {
    this.load();
  }
}
  • If the class was meant to appear in a view, give it the decorator that says so:

@Component({ selector: "app-data", template: "" })
export class DataComponent {
  ngOnInit() {
    this.load();
  }
}

Notes

A class carrying both a view decorator and a provider one is a component, so its hooks do run and it is left alone.

javascript.angular_lifecycle_interface asks a different question — whether a hook is backed by the matching implements clause. A hook can carry its interface and still sit on a class that never calls it.

© 2026 Xygeni. All rights reserved