Angular2 beta中的DynamicComponentLoader:"元素"没有组件指令

时间:2016-02-19 15:08:32

标签: angular

我无法让角度的DynamicComponentLoader在beta.6中工作。

我已采用动态组件加载from their docs的示例代码,并将其添加到plnkr, see here中的工作入门代码中。

以下是代码:

import {Component, DynamicComponentLoader, ElementRef} from 'angular2/core';


@Component({
  selector: 'child-component',
  template: 'Child'
})
class ChildComponent {
}


@Component({
    selector: 'my-app',
    template: '<h1>My First Angular 2 App</h1><div #child></div>'
})
export class AppComponent { 
  constructor(dcl: DynamicComponentLoader, elementRef: ElementRef) {
    dcl.loadIntoLocation(ChildComponent, elementRef, 'child');
  }
}

这是堆栈跟踪,它说:&#34;元素&#34;上没有组件指令:

EXCEPTION: Error during instantiation of AppComponent!.BrowserDomAdapter.logError @ angular2.dev.js:23083
angular2.dev.js:23083 ORIGINAL EXCEPTION: There is no component directive at element [object Object]BrowserDomAdapter.logError @ angular2.dev.js:23083
angular2.dev.js:23083 ORIGINAL STACKTRACE:BrowserDomAdapter.logError @ angular2.dev.js:23083
angular2.dev.js:23083 Error: There is no component directive at element [object Object]
    at new BaseException (angular2.dev.js:7351)
    at AppViewManager_.getNamedElementInComponentView (angular2.dev.js:6441)
    at DynamicComponentLoader_.loadIntoLocation (angular2.dev.js:12375)
    at new AppComponent (run.plnkr.co/mk31ybnwEtsiX31r/app/app.component.ts!transpiled:33)
    at angular2.dev.js:1420
    at Injector._instantiate (angular2.dev.js:11459)
    at Injector._instantiateProvider (angular2.dev.js:11395)
    at Injector._new (angular2.dev.js:11385)
    at InjectorInlineStrategy.instantiateProvider (angular2.dev.js:11149)
    at ElementDirectiveInlineStrategy.init (angular2.dev.js:9081)BrowserDomAdapter.logError @ angular2.dev.js:23083
angular2.dev.js:23083 ERROR CONTEXT:BrowserDomAdapter.logError @ angular2.dev.js:23083
angular2.dev.js:23083 _ContextcomponentElement: nullelement: my-appinjector: Injector__proto__: _ContextBrowserDomAdapter.logError @ angular2.dev.js:23083
angular2-polyfills.js:1152 DEPRECATION WARNING: 'dequeueTask' is no longer supported and will be removed in next major release. Use removeTask/removeRepeatingTask/removeMicroTask

1 个答案:

答案 0 :(得分:16)

更新4(和最终)

不推荐使用

DynamicComponentLoader (请参阅commit)。现在正确的方法是使用ViewContainerRefComponentResolver(请参阅下面的更新3)获取构造函数中的示例。

在beta.1中有一个突破性的变化。您无法再访问构造函数中的视图。因此,您可以将该示例移动到ngOnInit(),它将起作用。

changelog

引用
  

调用组件构造函数时尚未创建组件视图。 - &GT;使用onInit生命周期回调来访问组件的视图

export class AppComponent { 
  constructor(private dcl: DynamicComponentLoader, private elementRef: ElementRef) {

  }
  ngOnInit() {
    this.dcl.loadIntoLocation(ChildComponent, this.elementRef, 'child');
  }
}

使用您的示例工作检查此plnkr

更新

仅为了您的信息,我发送了一份PR(请参阅#7186)来修复源代码中的示例。所以希望他们会审查它并且它会通过。

更新2

自beta.16 loadIntoLocation被删除后,错误不再可重现。 loadNextToLocation现在需要ViewContainerRef。我开了一个新的PR(见#8241)来添加一个新的例子,原来的公关已经涵盖了其他一切。

代码示例(更新3)

如上所述,现在没有loadIntoLocation,但使用ViewContainerRefComponentResolver可以实现相同的行为。

constructor(cmpResolver: ComponentResolver, viewContainer: ViewContainerRef) {

  cmpResolver.resolveComponent(MyComponent)
    .then((factory: ComponentFactory) => {
        viewContainer.createComponent(factory, 0, viewContainer.injector)
    });
}

参考

关于loadNextToLocation,有两种方法,都使用ViewContainerRef

  • 使用元素本身的ViewContainerRef
constructor(private dcl: DynamicComponentLoader, viewContainer: ViewContainerRef) {
    dcl.loadNextToLocation(MyComponent, viewContainer).then(ref => {});
}
  • 在视图上使用某些元素
// Assume the next view
template : '<div #container></div>';

class MyClass {
   @ViewChild('container', {read: ViewContainerRef}) container : ViewContainerRef;

   constructor(private dcl: DynamicComponentLoader) {}

   ngAfterViewInit() {
      this.dcl.loadNextToLocation(MyDynamicCmp, this.container).then(ref => {});
   }
}

以上为例的plnkr