Angular2 beta 中的 DynamicComponentLoader:“元素处没有组件指令”

Posted

技术标签:

【中文标题】Angular2 beta 中的 DynamicComponentLoader:“元素处没有组件指令”【英文标题】:DynamicComponentLoader in Angular2 beta: "no component directive at element" 【发布时间】:2016-06-01 05:05:44 【问题描述】:

我无法让 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');
  

这里是堆栈跟踪,上面写着:“元素处没有组件指令”:

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】:

更新 4(和最终版本)

DynamicComponentLoader 已被弃用(请参阅commit)。现在正确的方法是在构造函数中使用ViewContainerRefComponentResolver(参见下面的更新3)作为示例。



在 beta.1 中发生了重大变化。您无法再访问构造函数中的视图。因此,您可以将该示例移至 ngOnInit(),它会起作用。

引用changelog

调用组件构造函数时尚未创建组件视图。 -> 使用 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)来添加它的新示例,其他所有内容都已包含在原始 PR 中。

代码示例(更新 3)

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

constructor(cmpResolver: ComponentResolver, viewContainer: ViewContainerRef) 

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

参考

ViewContainerRef#createComponent ComponentResolver#resolveComponent

关于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。

【讨论】:

您介意更新您的示例代码以反映 API 更改吗?

以上是关于Angular2 beta 中的 DynamicComponentLoader:“元素处没有组件指令”的主要内容,如果未能解决你的问题,请参考以下文章

Angular2 beta.12 和 RxJs 5 beta.3 的可观察到的错误

Angular2 beta14 Typescript routerLink绑定错误[重复]

Angular2 beta - 引导 HTTP_PROVIDERS - “意外令牌 <”

Angular2 beta 出现异常“没有路由器提供者!(RouterLink -> 路由器)”

Angular2 Hello World 之 2.0.0-beta.14

如何在 Angular 2 beta 的服务中有效地使用 Http 组件?