10

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

Dolan
  • 1,519
  • 4
  • 16
  • 36

3 Answers3

3

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() {}
}
Brady Isom
  • 1,635
  • 2
  • 13
  • 11
  • It still doesn't work! Instead, I get an error saying the app is not bootstrapped. Makes sense since you told me to remove the `bootstrap` line in `AppModule` [screenshot here](http://imgur.com/a/7o3Bi) – Dolan Nov 20 '16 at 16:41
  • 1
    Following the instructions one the Angular website, I also implemented the `ngDoBootstrap` method. That should get rid of your error. – Brady Isom Nov 21 '16 at 16:18
1

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

dmungin
  • 813
  • 6
  • 16
  • I am trying to UPGRADE the Angular1 component to Angular2 though because the majority of our code base is Angular2. Downgrading is not an option, unless we downgrade 5 months of work :P. Easier to upgrade 1 component right? – Dolan Feb 08 '17 at 22:47
  • I understand the confusion based on my answer, but take a look at the angular documentation here: https://angular.io/docs/ts/latest/api/upgrade/index/UpgradeAdapter-class.html If you check point 8 of the "Mental Model" it states "Angular 1 is always bootstrapped first and owns the bottom most view." This means you must have an Angular 1 app bootstrapped to something like document.documentElement (as in my plunker). From there you downgrade your Angular 2 AppComponent and place it inside that bottom view. You don't need to downgrade every other Ng2 component just the main entry component. – dmungin Feb 09 '17 at 14:50
1

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

LeeGenD
  • 11
  • 1