20

What I'm trying to do is to make Angular 2 simple component run inside angular 1 application. I was going through this official guide. I've faced some issue with injection:

Unknown provider: $$angularInjectorProvider <- $$angularInjector

The stack trace is making no sense, but is obvious that error is raised somewhere deep in the angular itself :)

The structure of my current app looks like this:

ng1.module.ts (entry point):

'use strict';

import { downgradeComponent } from '@angular/upgrade/static';

const angular = require('./lib/angular-wrapper');

const app = angular.module('application', []);

import { AppComponent } from './components/app/app.component.ts';
import { Ng2Module } from './ng2.module.ts';

app.directive(
  'app', 
  downgradeComponent({component: AppComponent}) as angular.IDirectiveFactory 
);

angular.bootstrap(document.body, ['application']);

ng2.module.ts:

import 'reflect-metadata';
import '@angular/core';

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UpgradeModule } from '@angular/upgrade/static';
import { AppComponent }  from './components/app/app.component.ts';

@NgModule({
  imports:      [ BrowserModule ],
  declarations: [ AppComponent ],
  entryComponents: [ AppComponent ]
})
export class Ng2Module { 
   ngDoBootstrap() {}
}

And app.component.ts:

import 'reflect-metadata';
import { Component } from '@angular/core';

@Component({
  selector: 'app',
  template: "<h1>HELLO WORLD!</h1>"
})
export class AppComponent {}

Asking for any idea on: what can cause the described above error?

2
  • Hey, I'm having the same issue with my Angular 1.2 app. Did you have any luck figuring it out? Commented Jun 28, 2017 at 14:17
  • @MaxPaymar it was on my previous job, unfortunately - not. I didn't resolve it. As far as any of the answers will help you - let me know, I'll accept it. Commented Jun 29, 2017 at 7:21

1 Answer 1

16
+500

This is caused by the UpgradeModule downgraded service that you are using here:

import { UpgradeModule } from '@angular/upgrade/static';

You are using it because you want the UpgradeModule to downgrade an Angular 2 component to angular JS.

If you dig into the code of the UpgradeModule you can find that this module defines a new angular module named $$UpgradeModule.

This module registers a value provider named $$angularInjector (the one in the error above) - this $$angularInjector thing is responsible for injecting Angular modules into angular JS.

The solution is to import the module in the imports statement so that angular JS will have access to its services.

You forgot to import the UpgradeModule. Here is the answer from the official documentation:

@NgModule({
  declarations: [Ng2HeroesComponent, Ng1HeroComponentWrapper],
  providers: [
    HeroesService,
    // Register an Angular provider whose value is the "upgraded" AngularJS service
    {provide: 'titleCase', useFactory: (i: any) => i.get('titleCase'), deps: ['$injector']}
  ],
  // All components that are to be "downgraded" must be declared as `entryComponents`
  entryComponents: [Ng2HeroesComponent],
  // We must import `UpgradeModule` to get access to the AngularJS core services
  imports: [BrowserModule, UpgradeModule]
})
class Ng2AppModule {
  ngDoBootstrap() { /* this is a placeholder to stop the boostrapper from complaining */
  }
}

so first you need to change your code to:

ng2.module.ts:

import 'reflect-metadata';
import '@angular/core';

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UpgradeModule } from '@angular/upgrade/static';
import { AppComponent }  from './components/app/app.component.ts';

@NgModule({
  imports:      [ BrowserModule, UpgradeModule ],
  declarations: [ AppComponent ],
  entryComponents: [ AppComponent ]
})
export class Ng2Module { 
   ngDoBootstrap() {}
}

Also in order to downgrade your component from ng2 to angular 1

You must create an AngularJS directive that will make this Angular component available inside AngularJS templates:

ng1AppModule.directive('Ng2Module', downgradeComponent({component: AppComponent}));

    function downgradeComponent(info: {   component: Type< This parameter is no longer used */   selectors?: string[]; }): any;

There is a very helpful post which explains in details how to create a hybrid angular application, and also the scenario when you have a v4 component and you want to use it in the v1 template.

Sign up to request clarification or add additional context in comments.

1 Comment

You seem to be absolutely right! I simply had to keep reading the tutorial. Will reward you the bounty in 23 hours when it's available.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.