I'm working through Angular's upgrade guide to learn how to embed AngularJS components in an Angular app. I've created a bare-bones Angular app using the Angular CLI and added a simple AngularJS module as a dependency.
When I run ng serve, the application compiles with no errors. However, at runtime, I get this message in the console:
Error: Trying to get the AngularJS injector before it being set.
What is causing this error, and how can I avoid it? I haven't deviated from the steps detailed in the upgrade guide.
Here's how I'm upgrading my AngularJS component inside my Angular app:
// example.directive.ts
import { Directive, ElementRef, Injector } from '@angular/core';
import { UpgradeComponent } from '@angular/upgrade/static';
// this is the npm module that contains the AngularJS component
import { MyComponent } from '@my-company/module-test';
@Directive({
    selector: 'my-upgraded-component'
})
export class ExampleDirective extends UpgradeComponent {
    constructor(elementRef: ElementRef, injector: Injector) {
        // the .injectionName property is the component's selector
        // string; "my-component" in this case.
        super(MyComponent.injectionName, elementRef, injector);
    }
}
And here's my app.module.ts:
// app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { UpgradeModule } from '@angular/upgrade/static';
import { ExampleDirective } from './example.directive';
import { myModuleName } from '@my-company/module-test';
@NgModule({
    declarations: [AppComponent, ExampleDirective],
    imports: [BrowserModule, AppRoutingModule, UpgradeModule],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule {
    constructor(private upgrade: UpgradeModule) {}
    ngDoBootstrap() {
        this.upgrade.bootstrap(document.body, [myModuleName], {
            strictDi: true
        });
    }
}
I'm using Angular 5.2.0.
I faced the same issue, and finally solved it. There are some steps to follow before bootstrap an hybrid Angular/angularjs application.
Install the UpgradeModule npm install @angular/upgrade
Wrap your "CompanyModule" (the module where all your company components are registered) into a new angularjs module (for instance: Ng1Shared). If you not have a module for your company components, it must be created. Than downgrade AppComponent as shown below.
const MyCompanyModule = angular
   .module('MyCompanyModule', [])
   .component('myComponent', MyComponent)
   .name;
const Ng1Shared = angular
   .module('Ng1Shared', [MyCompanyModule])
   .directive('appRoot', downgradeComponent({ component: AppComponent }))
   .name; 
Configure AppModule with basic imports (BrowserModule, CommonModule, UpgradeModule). Provide the angularjs' Injector to Angular; declare an "entryComponent" and remove the default bootstrap for AppComponent.
@NgModule({
  imports: [BrowserModule, CommonModule, UpgradeModule], 
  declarations: [AppComponent], 
  providers: [{provide: '$scope', useExisting: '$rootScope'}], // REQUIRED
  entryComponents: [AppComponent], // ADD AN ENTRY COMPONENT 
  // bootstrap: [AppComponent] MUST BE REMOVED
})
Set angularjs globally with a function provided by UpgradeModule itself and manually bootstrap Angular with DoBootstrap method provided by @angular/core.
export class AppModule implements DoBootstrap { 
  constructor(private upgrade: UpgradeModule) { }
  public ngDoBootstrap(app: any): void {
    setAngularJSGlobal(angular);
    this.upgrade.bootstrap(document.body, [Ng1Shared], { strictDi: false });
    app.bootstrap(AppComponent);
  }
}
Create a wrapper directive for every angularjs component and add it to AppModule's declaration array.
@Directive({
    selector: 'my-component'
})
export class MyComponentWrapper extends UpgradeComponent {
    @Input() title: string;
    constructor(elementRef: ElementRef, injector: Injector) {
      super('myComponent', elementRef, injector);
    }
}
I wrote a simple example available on stackblitz. For example purposes I added angularjs MyCompanyModule to another angularjs module, called Ng1Module. As you can see also property binding between angularjs and angular component works fine.
I hope it can be useful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With