Angular 2 Material。在一个组件中工作的相同 MdIcon 在另一个组件中失败

Angular 2 Material. Same MdIcon that works in one component fails in the other

我刚从 ng2 rc4 material2 alpha6 升级到 ng2 rc5 material 2 alpha7-2。当我使用 <md-icon>.

之前有效的代码弹出一个新错误

我看不到完整的错误文本,因为我得到的是 Observable_1.Observable.throw is not a function 错误(应用程序崩溃),堆栈跟踪中最上面的几行是:

MdIconRegistry.prototype.getNamedSvgIcon
    @angular2-material/icon/icon-registry.js:180:16
MdIcon.prototype.ngOnChanges
    @angular2-material/icon/icon.js:107:17

如果我 console.log()icon-registry.js @ line 180 上方查找的图标的 ID,我会看到 ic_lightbulb_outline_24px。这个图标出现在我的 svg sprite 中,但在我今天升级到 material 2 alpha 7-2 之前它显示正确。这是它在 svg sprite 中的部分:

...<svg viewBox="..." id="ic_lightbulb_outline_24px"><path d="..."/></svg>...

模板:

<md-icon svgIcon="ic_lightbulb_outline_24px"></md-icon>

在我的主要 AppComponent 我有

this._iconRegistry.addSvgIconSet('src/icons/sprite.defs.svg');

我还将 MdIconModule 导入到主 AppModule 中。真正令人费解的是

另外两条信息:

I've built a Plunkr 演示问题。您会注意到预先加载的组件(AppComponentHomeComponent)能够显示图标。但是,LazyLoadedComponent 不能。

下面是完整的堆栈跟踪:

MdIconRegistry.prototype.getNamedSvgIcon /@angular2-material/icon/icon-registry.js:180:16
MdIcon.prototype.ngOnChanges /@angular2-material/icon/icon.js:107:17
anonymous/_View_UserProfileComponent6.prototype.detectChangesInternal@UserProfileComponent.ngfactory.js:1318:29
AppView</AppView.prototype.detectChanges /@angular/core//bundles/core.umd.js:12586:13
AppView</AppView.prototype.detectContentChildrenChanges /@angular/core//bundles/core.umd.js:12604:17
anonymous/_View_UserProfileComponent1.prototype.detectChangesInternal@UserProfileComponent.ngfactory.js:294:3
AppView</AppView.prototype.detectChanges /@angular/core//bundles/core.umd.js:12586:13
AppView</AppView.prototype.detectContentChildrenChanges /@angular/core//bundles/core.umd.js:12604:17
anonymous/_View_UserProfileComponent0.prototype.detectChangesInternal@UserProfileComponent.ngfactory.js:37:3
AppView</AppView.prototype.detectChanges /@angular/core//bundles/core.umd.js:12586:13
AppView</AppView.prototype.detectViewChildrenChanges /@angular/core//bundles/core.umd.js:12612:17
anonymous/_View_UserProfileComponent_Host0.prototype.detectChangesInternal@UserProfileComponent.ngfactory.js:28:3
AppView</AppView.prototype.detectChanges /@angular/core//bundles/core.umd.js:12586:13
AppView</AppView.prototype.detectContentChildrenChanges /@angular/core//bundles/core.umd.js:12604:17
AppView</AppView.prototype.detectChangesInternal /@angular/core//bundles/core.umd.js:12596:13
AppView</AppView.prototype.detectChanges /@angular/core//bundles/core.umd.js:12586:13
AppView</AppView.prototype.detectViewChildrenChanges /@angular/core//bundles/core.umd.js:12612:17
AppView</AppView.prototype.detectChangesInternal /@angular/core//bundles/core.umd.js:12597:13
AppView</AppView.prototype.detectChanges /@angular/core//bundles/core.umd.js:12586:13
AppView</AppView.prototype.detectContentChildrenChanges /@angular/core//bundles/core.umd.js:12604:17
anonymous/_View_AppComponent0.prototype.detectChangesInternal@AppComponent.ngfactory.js:445:3
AppView</AppView.prototype.detectChanges /@angular/core//bundles/core.umd.js:12586:13
AppView</AppView.prototype.detectViewChildrenChanges /@angular/core//bundles/core.umd.js:12612:17
anonymous/_View_AppComponent_Host0.prototype.detectChangesInternal@AppComponent.ngfactory.js:30:3
AppView</AppView.prototype.detectChanges /@angular/core//bundles/core.umd.js:12586:13
ViewRef_</ViewRef_.prototype.detectChanges /@angular/core//bundles/core.umd.js:10804:58
ApplicationRef_</ApplicationRef_.prototype.tick/< /@angular/core//bundles/core.umd.js:10191:79
ApplicationRef_</ApplicationRef_.prototype.tick /@angular/core//bundles/core.umd.js:10191:17
ApplicationRef_/<.next/< /@angular/core//bundles/core.umd.js:10095:103
Zone</ZoneDelegate</ZoneDelegate.prototype.invoke /zone.js/dist/zone.js:323:20
NgZoneImpl/this.inner<.onInvoke /@angular/core//bundles/core.umd.js:9245:36
Zone</ZoneDelegate</ZoneDelegate.prototype.invoke /zone.js/dist/zone.js:322:20
Zone</Zone</Zone.prototype.run /zone.js/dist/zone.js:216:25
NgZoneImpl</NgZoneImpl.prototype.runInner /@angular/core//bundles/core.umd.js:9276:64
NgZone</NgZone.prototype.run /@angular/core//bundles/core.umd.js:9505:55
ApplicationRef_/<.next /@angular/core//bundles/core.umd.js:10095:73
EventEmitter</EventEmitter.prototype.subscribe/schedulerFn< /@angular/core//bundles/core.umd.js:9168:58
SafeSubscriber.prototype.__tryOrUnsub /rxjs/Subscriber.js:225:13
SafeSubscriber.prototype.next /rxjs/Subscriber.js:174:17
Subscriber.prototype._next /rxjs/Subscriber.js:124:9
Subscriber.prototype.next /rxjs/Subscriber.js:88:13
Subject.prototype._finalNext /rxjs/Subject.js:128:13
Subject.prototype._next /rxjs/Subject.js:120:13
Subject.prototype.next /rxjs/Subject.js:77:9
EventEmitter</EventEmitter.prototype.emit /@angular/core//bundles/core.umd.js:9156:58
NgZone</NgZone.prototype._checkStable /@angular/core//bundles/core.umd.js:9415:25
NgZone/this._zoneImpl<.onLeave /@angular/core//bundles/core.umd.js:9387:21
NgZoneImpl/this.inner<.onInvokeTask /@angular/core//bundles/core.umd.js:9239:29
Zone</ZoneDelegate</ZoneDelegate.prototype.invokeTask /zone.js/dist/zone.js:355:24
Zone</Zone</Zone.prototype.runTask /zone.js/dist/zone.js:256:29
ZoneTask/this.invoke /zone.js/dist/zone.js:423:29

有什么想法吗?

(交叉发布 on github

(这是的翻版,因为两期真的一模一样)

我发现因为 MdIconModule 本身在其 providers 数组中有 MdIconRegistry 服务,每次另一个模块导入它时,都会提供一个新的服务实例。因此,在 bootstrap 时间加载并且属于同一 AppModule 的所有组件共享该服务的同一个实例。但是,稍后加载的组件(通过延迟加载)具有 不同的 服务实例,因此无法看到在 bootstrap 时间注册的图标。

对于 ,我使用了一个特制模块的解决方法,它根本不使用 MdIconModule,而是单独声明 MdIcon class .然后我单独提供 MdIconRegistry 服务,并且只提供给根 AppComponent。结果是整个应用程序只有一个服务实例,并且在 bootstrap 时间注册的图标随处可用。

修改后的 MdIconFixedModule

@NgModule({
    imports: [CommonModule, HttpModule],
    declarations: [MdIcon],
    exports: [MdIcon],
    providers: [],//leave empty to avoid multiple instances of MdIconRegistry
})
export class MdIconFixedModule {
    static forRoot() {
        return {
            ngModule: MdIconFixedModule,
            //will be available only to whoever calls .forRoot()
            providers: [MdIconRegistry] 
        };
    }
}

只需要使用图标的模块可以导入 MdIconFixedModule,因为它不包含 MdIconRegistry。还需要注册图标的 AppModule 导入确实包含该服务的 MdIconFixedModule.forRoot()

此实现的详细信息can be seen here.

ng-Material 模块的限制是 fixed with the alpha 8 release