Search code examples
angulartypescriptdependency-injection

angular injectable chain stop working when moved into a library


In the following angular app named "app-standalone" I chained the injectables CoreService, OuterService, OutmostService and used them in the AppComponent (https://github.com/moky80/angular-injectable-chain/blob/master/app-standalone/src/app/app.component.ts) and they worked as expected:

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';
import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class CoreService {
  constructor() { console.log("Initialized Core");
} }
@Injectable({ providedIn: 'root' })
export class OuterService {
  constructor(private core: CoreService) {
    console.log("Initialized Outer");
}}
@Injectable({   providedIn: 'root' })
export class OutmostService { constructor(private outer: OuterService) {
    console.log("Initialized Outmost");
}}
@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, RouterOutlet],
  templateUrl: './app.component.html',
  styleUrl: './app.component.scss'
})
export class AppComponent {
  title = 'app-standalone';
  constructor(private outmost: OutmostService){
    console.log("Initialized AppComponent");
  }
}

In the next step, I moved CoreService, OuterService into the angular library named “lib-core” (https://github.com/moky80/angular-injectable-chain/blob/master/lib-core/projects/lib-core/src/lib/lib-core.service.ts):

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class CoreService {
  constructor() {
    console.log("Initialized Core");
  }
}

@Injectable({
  providedIn: 'root'
})
export class OuterService {
  constructor(private core: CoreService) {
    console.log("Initialized Outer");
  }
}

and created a new app named “app-uses-lib-core” (https://github.com/moky80/angular-injectable-chain/blob/master/app-uses-lib-core/src/app/app.component.ts) which uses the lib-core:

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';
import { Injectable } from '@angular/core';
import { OuterService } from 'lib-core';

@Injectable({   providedIn: 'root' })
export class OutmostService { constructor(private outer: OuterService) {
    console.log("Initialized Outmost");
}}
@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, RouterOutlet],
  templateUrl: './app.component.html',
  styleUrl: './app.component.scss'
})
export class AppComponent {
  title = 'app-uses-lib-core';
  constructor(private outmost: OutmostService){
    console.log("Initialized AppComponent");
  }
}

“app-uses-lib-core” got the run-time error “NG0203: inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with runInInjectionContext.”

I couldn’t see why moving the CoreService and OuterService into lib-core could cause an issue. Does somebody have an idea what is wrong with “lib-core” and “app-uses-lib-core” and how can I fix it provided that angular 17 is used?


Solution

  • The problem lines with how you are doing development, you need to use symlinks to link the library and the application.

    When I tried normal method of configuring the package using a local file no issues at all.

    "lib-core": "file:../lib-core/dist/lib-core/lib-core-0.0.0-watch+1726241313493.tgz",
    

    You can refer the below articles on how to use a library and application locally to do development.

    How to Develop Angular Libraries Locally?

    Create an Angular 14 Library, use it locally when developing and publish the package to npm


    Have made some small corrections to your library do check it out.

    Github Repo