角度2材质.在一个组件中工作的同一MdIcon在另一个组件中失败 [英] Angular 2 Material. Same MdIcon that works in one component fails in the other

查看:82
本文介绍了角度2材质.在一个组件中工作的同一MdIcon在另一个组件中失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚从带有material2 alpha6ng2 rc4升级到了带有material 2 alpha7-2ng2 rc5.当我使用<md-icon>之前,可以使用的代码会弹出一个新错误.

I just upgraded from ng2 rc4 with material2 alpha6 to ng2 rc5 with material 2 alpha7-2. A new error pops up on code that worked before when I use <md-icon>.

我看不到完整的错误文本,因为我收到了Observable_1.Observable.throw is not a function错误(应用程序崩溃),并且堆栈跟踪中的顶行是:

I cannot see the full error text because instead I get Observable_1.Observable.throw is not a function error (the app crashes), with the top lines in the stacktrace being:

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精灵中,但是在我今天升级到material 2 alpha 7-2之前,它可以正确显示.这是svg精灵中的部分:

If I console.log() the id of the icon sought just above icon-registry.js @ line 180, I see ic_lightbulb_outline_24px. This icon is present in my svg sprite, but it displayed properly before I upgraded today to material 2 alpha 7-2. Here is its section in the 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 also imported MdIconModule into the main AppModule. What's really puzzling is that

  • 来自同一个精灵文件的同一个图标可以在其他组件上使用,并且
  • 这在升级之前有效!

另外两条信息:

  • 此问题仅影响延迟加载的模块
  • 如果与<md-icon>相同的模板组件用于在应用启动时加载的组件的模板,则可以正常工作,但如果用于延迟加载的组件的模板,则将失败,并显示此错误
  • this problem only affects lazy-loaded modules
  • The same template component with <md-icon> will work fine if it's used on the template of a component loaded at app launch, but will fail with this error if it's used on the template of a component that was lazy-loaded

我已经构建了一个Plunkr 来演示此问题.您会注意到,热切加载的组件(AppComponentHomeComponent)能够显示该图标.但是,LazyLoadedComponent不能.

I've built a Plunkr demonstrating the problem. You'll notice that the eagerly loaded components (AppComponent and HomeComponent) are able to display the icon. However, LazyLoadedComponent cannot.

下面是完整的堆栈跟踪:

Below is the full stacktrace:

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

有什么想法吗?

(在github上交叉发布的 )

(cross-posted on github)

推荐答案

(这是

(this is a reproduction of my post here because the two issues are really the same)

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

I figured out that because MdIconModule itself has MdIconRegistry service in its providers array, every time another module imports it, a new instance of the service is provided. As a result, all components that are loaded at bootstrap time and that belong to the same AppModule share the same instance of this service. However, components loaded later (via lazy-loading) have a different instance of the service and as a result cannot see the icons registered at bootstrap time.

借助詹姆斯的帮助,我使用了特制模块的变通办法,该模块根本不使用MdIconModule,而是仅声明MdIcon类.然后,我分别提供MdIconRegistry服务,并且仅提供给根AppComponent.结果是,整个应用程序范围内只有一个实例,并且在引导时注册的图标随处可见.

With help from James, I've used the workaround of a specially crafted module that does not use MdIconModule at all, but rather declares the MdIcon class alone. I then provide the MdIconRegistry service separately, and only to the root AppComponent. The result is that there is only one instance of the service app-wide and icons registered at bootstrap time are available everywhere.

修改后的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().

Modules that need to just use icons can import MdIconFixedModule as this doesn't contain the MdIconRegistry. The AppModule that also needs to register icons imports MdIconFixedModule.forRoot() which does contain the service.

此实现的详细信息可以在此处查看.

此ng-Material Modules的限制规定为已在alpha 8版本中修复.

This limitation of ng-Material Modules is slotted to be fixed with the alpha 8 release.

这篇关于角度2材质.在一个组件中工作的同一MdIcon在另一个组件中失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆