angularjsangularangular-servicesangular-hybrid

Angular Hybrid Error: Trying to get the AngularJS injector before it being set


How to use AngularJS service in Angular 5 component?

I have AngularJS application and i am trying to make hybrid app but not able to use AngularJS service insight Angular component : getting error

ERROR Error: Trying to get the AngularJS injector before it being set.

my main.ts is

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);

app.module :

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, InjectionToken } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { UpgradeModule, downgradeComponent } from '@angular/upgrade/static';
import { AppComponent } from './app.component';
import { SignInComponent } from "./modules/login/components/sign-in/sign-in.component";
import { authServiceProvider } from './shared/angularJS-upgraded-providers';



@NgModule({
    declarations: [
        AppComponent,
        SignInComponent
    ],
    imports: [
        BrowserModule,
        UpgradeModule,
        FormsModule
    ],
    entryComponents: [
        SignInComponent
    ],
    providers: [authServiceProvider],
    bootstrap: [SignInComponent]
})

export class AppModule {
    ngDoBootstrap() {}
}

angularJS-upgraded-providers.ts :

import { InjectionToken } from "@angular/core";
export const AuthService = new InjectionToken<any>('authService');

export function authServiceFactory(i: any) {
  return i.get('authService');
}

export const authServiceProvider = {
  provide: AuthService,
  useFactory: authServiceFactory,
  deps: ['$injector']
};

and sign-in.component.ts :

import { Component, Inject } from '@angular/core';
import {AuthService} from "../../../../shared/angularJS-upgraded-providers";

@Component({
    selector: 'sign-in',
    template: require('./sign-in.component.html')
})

export class SignInComponent {
    constructor(
        @Inject(AuthService) private authService: any) {
    }
}

When I remove SignInComponent constructor part code compiles well but with @Inject(AuthService) private authService: any) { } part I am getting an error :

Trying to get the AngularJS injector before it being set.

Please give me some suggesting how can I implement angularJS service insight Angular component. Thanks

P.S. my package.json :

{
  "name": "test",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "start": "webpack-dev-server --port=4200 --open chrome"
  },
  "dependencies": {
    "@angular/common": "^5.2.11",
    "@angular/compiler": "^5.2.11",
    "@angular/core": "^5.2.11",
    "@angular/forms": "^5.2.11",
    "@angular/http": "^5.2.11",
    "@angular/platform-browser": "^5.2.11",
    "@angular/platform-browser-dynamic": "^5.2.11",
    "@angular/router": "^5.2.11",
    "@angular/upgrade": "^5.2.11",
    "core-js": "^2.5.7",
    "reflect-metadata": "^0.1.12",
    "rxjs": "^5.5.11",
    "zone.js": "^0.8.26"
  },
  "devDependencies": {
    "@types/jquery": "^3.3.6",
    "@types/node": "^8.10.23",
    "awesome-typescript-loader": "^5.2.0",
    "css-loader": "^1.0.0",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "raw-loader": "^0.5.1",
    "style-loader": "^0.22.1",
    "ts-loader": "3.2.0",
    "typescript": "^2.9.2",
    "webpack": "^4.16.5",
    "webpack-cli": "^3.1.0",
    "webpack-dev-server": "^3.1.5"
  }
}

And AngularJS version : 1.6.8


Solution

  • This means you are pulling in an AngularJS dependency somewhere in your component tree. It may be in your immediate component or some dependency further down the line.

    To debug:

    Method 1

    Add a debugger statement immediately before your bootstrap call:

    it('should render the component', () => {
       debugger;
       bootstrap(Ng2AppComponent);
       ...
     });
    
    1. With your JS Console open, let the test run and pause at the debugger location.
    2. Click the Stop/Pause icon (in the sidebar on the 'sources' tab) and checkmark "Pause on Exceptions". Unpause the debugger.
    3. The debugger should stop within a call to injectorFactory. Use the stack explorer to find calls to resolveNgModuleDep. These will be recursive, so the top of the stack will be closer to a leaf node, while calls further down the stack will be closer to your component being tested. Look for lines like: tokenKey = "ServiceName". This is potentially your offending service.
    4. Dive down the stack one more layer to find which component tried to inject that service.
    5. Within your test, mock out a provider to handle that specific injection. Note that this code assumes only one problem injection. For multiple injector issues, you will need to special case these:
     beforeEach(() => {
       setupModule({
         imports: [
           ...
         ],
         providers: [
           {
             provide: '$injector',
             useValue: {
               get: () => {
                 return new MockService();  // enhance as needed
               },
             }
           }
         ],
       });
    

    Method 2

    1. Mock out a provider for the $injector call, and return an empty object.
    beforeEach(() => {
       setupModule({
         imports: [
           ...
         ],
         providers: [
           {
             provide: '$injector',
             useValue: {
               get: (serviceName?: string) => {
                console.log('looking for serviceName:', serviceName);
                return {};  // this will break things differently
               },
             }
           }
         ],
       });
    
    1. Look at your console output to find the offending service / signature. This may or may not involve less work than than Method 1.