Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 UpgradeComponent missing $injector

I am trying to upgrade an Angular1 component and consume it in my Angular2 app by following the official Angular2 documentation here under "Using Angular 1 Component Directives from Angular 2 Code", but it gives the following error:

error_handler.js:54 TypeError: Cannot read property 'get' of undefined
    at ChartDirective.UpgradeComponent (upgrade_component.js:97)

enter image description here

Upon closer inspection on line 97, this.$inspector is undefined:

enter image description here

My code is very simple:

import { Directive, ElementRef, Injector } from '@angular/core';
import { UpgradeComponent } from '@angular/upgrade/static';

export const coolComponent = {
  template: 'cool',
  controller: function() {
  }
};

@Directive({
    selector: 'app-chart'
})
export class ChartDirective extends UpgradeComponent {

    constructor(elementRef: ElementRef, injector: Injector) {
        super('coolComponent', elementRef, injector);
    }
}

My main.ts for bootstrapping is:

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule);

Here is the simplified version of the problem, with minimal reproduction steps: https://github.com/dolanmiu/angular2-upgrade-test

It is generated by angular-cli

like image 881
Dolan Avatar asked Nov 18 '16 12:11

Dolan


3 Answers

I had a similar problem. To fix my issue, I removed the following line from my AppModule definition:

bootstrap: [AppComponent]

In my case, I also had to add the AppComponent to my entryComponents section:

entryComponents: [AppComponent]

You also need to implement the ngDoBootstrap method, if you haven't already:

export class AppModule {
  ngDoBootstrap() {}
}
like image 159
Brady Isom Avatar answered Oct 21 '22 14:10

Brady Isom


Here is a plunker of a working example I created. I was having the same issue as you described. The key for me was to downgrade my AppComponent and place the downgraded component into the Angular 1 app:

import { App1Component } from './app1.component';
import { App } from './app';
import { downgradeComponent } from '@angular/upgrade/static';

angular.module('ng1', [])
  .directive(
      'ng2AppComponent',
      downgradeComponent({component: App})
    )
  .component('app1Component', App1Component);

index.html:

...
<body>
   <ng2-app-component></ng2-app-component>
</body>
...

Then I needed to do as described above and move AppComponent to entryComponents in my AppModule.

@NgModule({
  imports: [ BrowserModule, UpgradeModule ],
  declarations: [ App, App1Directive ],
  entryComponents: [ App ]
})
export class AppModule {
  ngDoBootstrap() {}
}

In my example the downgraded Angular 2 AppComponent is in the index.html but you can place it in whatever Angular 1 template you want if that makes more sense for your application.

https://plnkr.co/edit/YSw63x10WAEivMWdNffj?p=preview

like image 31
dmungin Avatar answered Oct 21 '22 14:10

dmungin


It can't use ng1 directive upgraded by UpgradeComponent,when you use ng2 to bootstrap your application.

You need use ng1 to bootstrap application and ng2 component,then use ng1 directive in ng2 component.

Which needs remove all content in bootstrap of @NgModule,and move AppComponent to entryComponents,then empty ngDoBootstrap() in AppModule:

@NgModule({
    bootstrap: [  ],
    //...
    entryComponents: [
        AppComponent,
        //...
    ]
})
export class AppModule {
    public ngDoBootstrap() {}
}

After that,downgrade AppComponent:

import { AppComponent } from '../app.component';
import { downgradeComponent } from '@angular/upgrade/static';
//...
angular.directive(
    'app', downgradeComponent({
        component: AppComponent
    }) as angular.IDirectiveFactory
);

And now,you can render a ng1 directive upgraded,in ng2 component.

More Details:Angular2 UpgradeComponent missing $injector

like image 41
LeeGenD Avatar answered Oct 21 '22 12:10

LeeGenD