简体   繁体   中英

Angular Upgrade - can't use upgraded component as entry component

I'm using Angular Upgrade module with components upgraded from AngularJS. When I use components inside templates they are working fine but when I try to use them as entry components I receive an error:

MyNgComponent cannot be used as an entry component.

Probably it's because upgraded components are defines as directives. I've also tried to wrap into another component but in this case it gives me an error when tries to create a component instance:

NullInjectorError: No provider for $scope!

$scope is requested by internal UpgradeComponent implementation and it's resolved fine if component is used in a template.

Is it a hybrid mode limitation or is there any way to use it as entry component?

Entry component is needed because I need to instantiate this component from JS and manually attach to non-angular DOM element

Seems to be a limitation of a hybrid mode. In my case it was necessary to dynamically create upgraded components and attach them to DOM. In this case it's possible to use the following workaround:

  1. Create a regular Angular Component as a wrapper for upgraded AngularJS directive so that it's template only contains an upgraded directive
  2. Add this wrapper component to entryComponents module section
  3. Dynamically instantiate this wrapper component using an injector of root hybrid component

For example, I have a have a dummy AngularJS directive

angular.module('app').component('myComponent', {
  template: 'dummy content',
  controller: class {},
  controllerAs: 'vm'
});

@Directive({
  selector: 'my-component'
})
export class MyUpgradedDirective extends UpgradeComponent {
  constructor(elementRef: ElementRef, injector: Injector) {
    super('myComponent', elementRef, injector);
  }
}

Create a wrapper component:

@Component({
  selector: 'app-nested',
  template: '<my-component></my-component>'
})
export class WrapperComponent { }

Add it to entryComponents

@NgModule({
  imports:      [ BrowserModule, UpgradeModule ],
  declarations: [ AppComponent, NestedComponent, MyUpgradedDirective ],
  entryComponents: [ AppComponent, NestedComponent ] // here
})

Create a wrapper instance using an injector from root hybrid component:

function createMyComponent<T>(componentFactoryResolver: ComponentFactoryResolver, injector: Injector /* must be passed from root hybrid component */, component: Type<T>) {
  return componentFactoryResolver
    .resolveComponentFactory(component)
    .create(injector);
}

Here are some details: https://github.com/angular/angular/issues/27432

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM