inject() must be called from an injection context

AngularTypescript

Angular Problem Overview


I am trying to export my Angular app as an npm module to be consumed by other applications, but am running into some difficulties. I have not been able to find this error anywhere else on the internet, and am at my wit's end.

I followed this tutorial: https://medium.com/@nikolasleblanc/building-an-angular-4-component-library-with-the-angular-cli-and-ng-packagr-53b2ade0701e

I used ng-packagr to export my app as an npm module. I can successfully install it from a local folder on a barebones test app, but cannot get it to display my app.

Error:

    AppComponent.html:1 ERROR Error: inject() must be called from an injection context
    at inject (core.js:1362)
    at ChangeStackService_Factory (template-wiz.js:2074)
    at _callFactory (core.js:8223)
    at _createProviderInstance (core.js:8181)
    at resolveNgModuleDep (core.js:8156)
    at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (core.js:8849)
    at resolveDep (core.js:9214)
    at createClass (core.js:9094)
    at createDirectiveInstance (core.js:8971)
    at createViewNodes (core.js:10191)

template-wiz.module.ts (Module being exported)

    import { NgModule, ChangeDetectorRef, ComponentFactoryResolver } from '@angular/core';
    import { TemplateWizComponent } from './template-wiz.component';
    import { BrowserModule } from '@angular/platform-browser';
    import { FormsModule } from '@angular/forms';
    import { HttpClientModule } from '@angular/common/http';
    import { BlockListDirective } from './Directives/block-list.directive';
    import { TemplateItemsDirective } from './Directives/template-items.directive';
    import { ContextMenuComponent, SeperatorComponent, DragBoxComponent, SnapLineComponent, PropertiesComponent, ToolboxComponent } from './Components'
    import { AddressBlockComponent, TextBlockComponent, ImageBlockComponent, DataBlockComponent } from './Data-Blocks';
    import { BlockFactoryService, BlockRegistryService, DisplayInfoService, MouseClickService, SavingService, SnapService, TextHelperService, UserModeService } from './Services';
    import { PageContextMenuComponent } from './Components/page-context-menu/page-context-menu.component';
    import { CamelToWordsPipe } from './Pipes/camel-to-words.pipe';
    import { PdfPublisherService } from './Services/pdf-publisher/pdf-publisher.service';
    import { GradientBlockComponent } from './Data-Blocks/gradient-block/gradient-block.component';
    import { PropToTypePipe } from './Pipes/prop-to-type.pipe';
    import { ShapeBlockComponent } from './Data-Blocks/shape-block/shape-block.component';
    import { CommonModule } from '@angular/common';
    import { ModuleWithProviders } from '@angular/compiler/src/core';


    @NgModule({
      imports: [
        CommonModule,
        FormsModule,
        HttpClientModule
      ],
      entryComponents: [
        AddressBlockComponent,
        ContextMenuComponent,
        DragBoxComponent,
        GradientBlockComponent,
        ImageBlockComponent,
        PageContextMenuComponent,
        SeperatorComponent,
        ShapeBlockComponent,
        SnapLineComponent,
        TextBlockComponent
      ],
      declarations: [
        TemplateWizComponent,
        DataBlockComponent,
        AddressBlockComponent,
        SeperatorComponent,
        BlockListDirective,
        TemplateItemsDirective,
        ImageBlockComponent,
        TextBlockComponent, DragBoxComponent,
        SnapLineComponent,
        ToolboxComponent,
        PropertiesComponent,
        ContextMenuComponent,
        PageContextMenuComponent,
        GradientBlockComponent,
        CamelToWordsPipe,
        PropToTypePipe,
        ShapeBlockComponent
      ],
      providers: [
        BlockFactoryService,
        BlockRegistryService,
        DisplayInfoService,
        MouseClickService,
        SavingService,
        SnapService,
        TextHelperService,
        UserModeService,
        PdfPublisherService
      ],
      //bootstrap: [TemplateWizComponent],
      exports: [
        TemplateWizComponent
      ]
    })
    export class TemplateWizModule {
      static forRoot(): ModuleWithProviders {
        return {
          ngModule: TemplateWizModule,
          providers: [
            ComponentFactoryResolver
          ]
        }
      }
    }

app.module.ts (Bare bones test app using my module)

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { FormsModule } from '@angular/forms';
    import { HttpClientModule } from '@angular/common/http';
    import { AppComponent } from './app.component';
    import { TemplateWizModule } from 'template-wiz';

    @NgModule({
      declarations: [
        AppComponent,
      ],
      imports: [
        BrowserModule,
        FormsModule,
        TemplateWizModule.forRoot(),
        HttpClientModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }

Any help or pointers at all would be appreciated, thank you.

Angular Solutions


Solution 1 - Angular

There seems to be an issue when using npm link when consuming the library.

Solution: use projects.$name.architect.build.options.preserveSymlinks: true in the angular.json file of the client project, not the library.

Further information: https://github.com/angular/angular/issues/25813

Solution 2 - Angular

Here's what solved it for me :

Add the following line in tsconfig.app.json under compilerOptions :

"paths": { "@angular/*": [ "../node_modules/@angular/*" ] }

Source : https://github.com/angular/angular/issues/25813#issuecomment-500091900

Solution 3 - Angular

I had the same error.

I found that I was importing Inject from @angular/core instead of @angular/core/testing.

Hope that helps!

Solution 4 - Angular

Same issue but my case was dumber...

I had npm install something in the wrong folder.

So just rm the wrong "node_modules" and npm install in the good folder x)

Solution 5 - Angular

I my case it was because this code was missing in test-setup.ts. I had only the first 2 lines.

import 'jest-extended';
import 'jest-preset-angular/setup-jest';

import { getTestBed } from '@angular/core/testing';
import {
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';

getTestBed().resetTestEnvironment();
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), {
  teardown: { destroyAfterEach: false },
});

What made it a bit difficult was that I got a different unhelpul error even after adding this code because it was an Angular library package with its own package.json where the dependency @angular/platform-browser-dynamic was missing.

Above helped, but I removed this code again.
What actually helped was https://stackoverflow.com/a/68718393/217408

A publishable package

  • must not have dependencies, only peerDependencies
  • npm install should not be run. The library must not contain a node_modules directory.

Having dependencies and node_modules worked fine since months, but suddenly started failing and now even older commits don't work anymore without fixing above points.

Solution 6 - Angular

I ran in a similar problem. Using a angular lib within an angular app with npm link.

As mentioned: "Solution: use projects.$name.architect.build.options.preserveSymlinks: true in the angular.json file of the client project, not the library." works when serving the appliction with "ng serve".

However the error still was there when unit testing the application with "ng test". Adding preserveSymLinks in the the angular.json file here:

projects.$name.architect.test.options.preserveSymlinks: true

fixed that as well.

Solution 7 - Angular

I got the error message inject() must be called from an injection context when I was creating a tree-shakable InjectionToken that used another InjectionToken in its factory, e.g.

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

import { dependeeToken } from './dependee.token';

export const dependingToken = new InjectionToken<string>('depending', {
  factory: () => inject(dependeeToken) + ' depending';
  providedIn: 'root',
});

Instead, I added a provider for the depending InjectionToken to an NgModule.

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

import { dependeeToken } from './dependee.token';
import { dependingToken } from './depending.token';

@NgModule({
  providers: [
    {
      deps: [dependeeToken],
      provide: dependingToken,
      useFactory: dependee => dependee + ' depending',
    }
  ],
})
export class DependingModule {}

package.json excerpt

{
  "dependencies": {
    "@angular/compiler": "6.1.9",
    "@angular/core": "6.1.9"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "0.8.4",
    "@angular/cli": "6.2.4",
    "@angular/compiler-cli": "6.1.9",
    "typescript": "2.9.2"
  }
}

Solution 8 - Angular

What solved it for me was to use the providedIn property in the Injectable decorator instead of registering the service in the app module in the providers for the service which was causing me this error message.

@Injectable({
  providedIn: 'root'
})
export class HeroService {}

Solution 9 - Angular

Same issue here

My Case: When I was using Mat Dialog

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

 constructor(
    @Inject(MAT_DIALOG_DATA) public data: any,
    public matDialogRef: MatDialogRef<MatConfirmDialogComponent>) { }

inject & Inject are different:

inject is a function and Inject is Interface

I hope this helps someone who comes finding the same scenario.

Solution 10 - Angular

I had this error when building angular 9.0.0-next.0 with ng build --prod command. Downgrading to version ~8.2.8 made my angular app work again.

It was working well in development with ng serve, so it seems to be linked to Ivy.

Solution 11 - Angular

If the error appears on Karma with tests, just delete de node_modules folder and install again.

Solution 12 - Angular

I came across a similar problem in testing an Angular application. The application imported a Service that had been installed from @bit with npm. The service depended on the MatSnackBar which seemed to be causing the same error as the OP.

To get the tests to run I instantiated the service when configuring the testing module.

In the example below, the AsyncUIFeedbackService was installed from Bit via npm. Setting the useValue to a new instance of the service, and stubbing the MatSnackBar worked great.

await TestBed.configureTestingModule({
      declarations: [GeneralInfoComponent],
      providers: [
        FormBuilder,
        { provide : AsyncUIFeedbackService, 
          useValue: new AsyncUIFeedbackService({} as MatSnackBar)}, // <----Create the service
      ],
      imports: [AsyncUIFeedbackModule]
    }).compileComponents();

Solution 13 - Angular

I found that I was importing Inject from @angular/core instead of @angular/core/testing.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjvinyardView Question on Stackoverflow
Solution 1 - Angulardav1dView Answer on Stackoverflow
Solution 2 - AngularcheseauxView Answer on Stackoverflow
Solution 3 - Angularuser10161436View Answer on Stackoverflow
Solution 4 - AngularGalahadView Answer on Stackoverflow
Solution 5 - AngularGünter ZöchbauerView Answer on Stackoverflow
Solution 6 - AngularMarco van ZuylenView Answer on Stackoverflow
Solution 7 - AngularLars Gyrup Brink NielsenView Answer on Stackoverflow
Solution 8 - AngularGerrosView Answer on Stackoverflow
Solution 9 - AngularShabbir IsmailView Answer on Stackoverflow
Solution 10 - AngularMatt WalterspielerView Answer on Stackoverflow
Solution 11 - AngularCarlos Tenorio PérezView Answer on Stackoverflow
Solution 12 - AngularMR-DSView Answer on Stackoverflow
Solution 13 - AngularV. NogueiraView Answer on Stackoverflow