角度2材质.在一个组件中工作的同一MdIcon在另一个组件中失败 [英] Angular 2 Material. Same MdIcon that works in one component fails in the other
问题描述
我刚刚从带有material2 alpha6
的ng2 rc4
升级到了带有material 2 alpha7-2
的ng2 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 来演示此问题.您会注意到,热切加载的组件(AppComponent
和HomeComponent
)能够显示该图标.但是,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
有什么想法吗?
(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屋!