【发布时间】:2016-07-08 12:44:13
【问题描述】:
我目前正在从事一个从 Angular 2 beta 13 升级到 RC 4 的项目。 在升级之前,使用此服务向正在加载数据的任何页面动态添加和删除简单组件(简单微调器)的功能运行良好:
(SinnerService.ts)
import {Injectable, DynamicComponentLoader, ApplicationRef, ElementRef,
ComponentRef} from '@angular/core';
import {Spinner} from './spinner';
@Injectable()
export class SpinnerService {
spinnerComp: ComponentRef;
constructor(private _componentLoader: DynamicComponentLoader, private _appRef: ApplicationRef) {
}
public start() {
let elementRef: ElementRef = this._appRef['_rootComponents'][0].location;
return this.startInside(elementRef, null);
}
public startInside(elementRef: ElementRef, anchorName: string) {
let spinnerRef = (!anchorName) ?
this._componentLoader.loadNextToLocation(Spinner, elementRef, anchorName) :
this._componentLoader.loadNextToLocation(Spinner, elementRef);
spinnerRef.then((compRef: ComponentRef) => {
this.spinnerComp = compRef;
});
}
public stop() {
if (this.spinnerComp) {
this.spinnerComp.dispose();
}
}
}
在升级期间,对类进行了更改以匹配对 Angular 2 所做的更改。 生成的文件导致发生异常,显示在更新的代码下方:
(为 RC 4 更改了 SinnerService.ts):
import {Injectable, DynamicComponentLoader, ApplicationRef, ViewContainerRef, ComponentRef} from '@angular/core';
import {Spinner} from './spinner';
@Injectable()
export class SpinnerService {
spinnerComp: ComponentRef<any>;
constructor(private _componentLoader: DynamicComponentLoader, private _appRef: ApplicationRef) {
}
public start() {
let elementRef: ViewContainerRef = this._appRef['_rootComponents'][0].location;
return this.startInside(elementRef, null);
}
public startInside(elementRef: ViewContainerRef, anchorName: string) {
let spinnerRef = (!anchorName) ?
this._componentLoader.loadNextToLocation(Spinner, elementRef) :
this._componentLoader.loadNextToLocation(Spinner, elementRef);
spinnerRef.then((compRef: ComponentRef<any>) => {
this.spinnerComp = compRef;
});
}
public stop() {
if (this.spinnerComp) {
this.spinnerComp.destroy();
}
}
}
错误:
EXCEPTION: Error: Uncaught (in promise): TypeError:
location.createComponent is not a function
browser_adapter.ts:82
EXCEPTION: Error: Uncaught (in promise): TypeError:
location.createComponent is not a functionBrowser DomAdapter.logError @ browser_adapter.ts:82
browser_adapter.ts:82
STACKTRACE:BrowserDomAdapter.logError @ browser_adapter.ts:82
browser_adapter.ts:82
Error: Uncaught (in promise): TypeError:
location.createComponent is not a function
at resolvePromise (zone.js:538)
at resolvePromise (zone.js:523)
at zone.js:571
at ZoneDelegate.invokeTask (zone.js:356)
at Object.onInvokeTask (ng_zone_impl.ts:61)
at ZoneDelegate.invokeTask (zone.js:355)
at Zone.runTask (zone.js:256)
at drainMicroTaskQueue (zone.js:474)
at XMLHttpRequest.ZoneTask.invoke (zone.js:426) BrowserDomAdapter.logError @ browser_adapter.ts:82 zone.js:461
Unhandled Promise rejection: location.createComponent is not a
function ; Zone: angular ; Task: Promise.then ; Value: TypeError:
location.createComponent is not a function(…) consoleError @ zone.js:461
zone.js:463
Error: Uncaught (in promise): TypeError: location.createComponent is not a function(…)
所以,我阅读了很多关于这个主题的内容,并尝试了几种使用 DynamicComponentLoader.loadNextToLocation(...) 的方法。在那次调查中,我还注意到该组件似乎已被 Google 弃用。 (https://angular.io/docs/js/latest/api/core/index/DynamicComponentLoader-class.html)
Google 在 Angular 2 上保留的列表发生了变化,提到您必须使用 ViewContainerRef 而不是 ElementRef,但没有示例说明应该如何做到这一点。
经过更多的挖掘,我看到了一些使用 ComponentResolver 而不是 DynamicComponentLoader.loadNextToLocation(...) 的建议,如下所示:
(SinnerService.ts 改为使用 ComponentResolver):
import {Injectable, DynamicComponentLoader, ApplicationRef, ViewContainerRef, Component, ComponentRef, ComponentResolver, ComponentFactory, ViewChild} from '@angular/core';
import {Spinner} from './spinner';
@Injectable()
export class SpinnerService {
spinnerComp: ComponentRef<any>;
constructor(private _componentLoader: DynamicComponentLoader, private _appRef: ApplicationRef,
private _resolver: ComponentResolver) {
}
public start() {
let elementRef: ViewContainerRef = this._appRef['_rootComponents'][0].location;
return this.startInside(elementRef, null);
}
public startInside(elementRef: ViewContainerRef, anchorName: string) {
//let spinnerRef = (!anchorName) ?
// this._componentLoader.loadNextToLocation(Spinner, elementRef) :
// this._componentLoader.loadNextToLocation(Spinner, elementRef);
DynamicComponentLoader
//spinnerRef.then((compRef: ComponentRef<any>) => {
// this.spinnerComp = compRef;
//});
let spinnerRef = this._resolver.resolveComponent(Spinner);
spinnerRef.then((factory: ComponentFactory<any>) => {
this.spinnerComp = elementRef.createComponent(factory)
});
}
public stop() {
if (this.spinnerComp) {
this.spinnerComp.destroy();
}
}
}
但是,这也导致抛出一个与之前的错误几乎相同的错误:
EXCEPTION: Error: Uncaught (in promise): TypeError:
elementRef.createComponent is not a function
browser_adapter.ts:82
EXCEPTION: Error: Uncaught (in promise): TypeError:
elementRef.createComponent is not a function BrowserDomAdapter.logError @ browser_adapter.ts:82 browser_adapter.ts:82
STACKTRACE:BrowserDomAdapter.logError @ browser_adapter.ts:82
browser_adapter.ts:82
Error: Uncaught (in promise): TypeError:
elementRef.createComponent is not a function
at resolvePromise (zone.js:538)
at zone.js:574
at ZoneDelegate.invokeTask (zone.js:356)
at Object.onInvokeTask (ng_zone_impl.ts:61)
at ZoneDelegate.invokeTask (zone.js:355)
at Zone.runTask (zone.js:256)
at drainMicroTaskQueue (zone.js:474)
at XMLHttpRequest.ZoneTask.invoke (zone.js:426)
BrowserDomAdapter.logError @ browser_adapter.ts:82
zone.js:461
Unhandled Promise rejection: elementRef.createComponent is not a
function ; Zone: angular ; Task: Promise.then ; Value: TypeError:
elementRef.createComponent is not a function(…) consoleError @ zone.js:461
zone.js:463
Error: Uncaught (in promise): TypeError: elementRef.createComponent is
not a function(…) consoleError @ zone.js:463
SignalRService.js:40 Event hub started.
所以,这个重要的功能似乎被破坏了。
还有其他人成功使用过这个功能吗?
我在他们的 GitHub 存储库上向 Google 提交了一个错误,但我希望其他人可能已经遇到了这个问题,并且有一个有效的方法来解决这个问题或解决这个问题。
任何帮助将不胜感激。谢谢!
【问题讨论】:
-
听起来像` let elementRef: ViewContainerRef = this._appRef['_rootComponents'][0].location; ` 没有返回
ViewContainerRef。你检查了吗? -
嗨,比尔,你解决了这个问题吗?
标签: angular