I'm using Angular 2 rc 5
with ng2-Material alpha 7-2
.
The basic problem is that using <md-icon svgIcon='icon'>
to show the same icon from the same svg file will work in one component but not the other even though MdIconModule
and MdIconRegistry
are provided to the root AppModule
To replicate the problem
- Open this plunker
- Notice that
MdIconModule
and MdIconRegistry
are imported as part of MaterialModule.forRoot()
into the main AppModule
- Open the
AppComponent
and notice the call to addSvgIconSet()
to register icons
- In the template,
<md-icon svgIcon='ic_account_box_24px'>
is used to display the icon. In the view the icon is shown successfully above the nav bar.
- Open
app/crisis-center/crisis.list.component
and open the Crisis Center in the view.
- Note in the template, the same
<md-icon>
is present. However, no icon is displayed above the crisis list in the view. The DOM inspector from browser dev tools shows that the angular parser didn't even recognize it as an angular component (in the dom, it's left exactly as in the code)
Because I imported the icon module and service into the root module I expected the service to be a singleton available to the whole app. Since I use that service to register the icons with iconRegistry.addSvgIconSet()
in my bootstrapped AppComponent
, I expected the icons to be accessible throughout the app.
PS: this may be related to what I reported yesterday, although in that case the app crashes; in this case the icon is just not shown.
import { NgModule, ModuleWithProviders } from '@angular/core';
import { MdButtonModule } from '@angular2-material/button';
import { MdCardModule } from '@angular2-material/card';
import { MdCheckboxModule } from '@angular2-material/checkbox';
import { MdCoreModule } from '@angular2-material/core';
import { MdInputModule } from '@angular2-material/input';
import { MdProgressCircleModule } from '@angular2-material/progress-circle';
import { MdToolbarModule } from '@angular2-material/toolbar';
import { MdMenuModule } from '@angular2-material/menu';
import { MdIconModule} from '@angular2-material/icon';
@NgModule({
exports: [
MdButtonModule,
MdCardModule,
MdCheckboxModule,
MdCoreModule,
MdInputModule,
MdProgressCircleModule,
MdToolbarModule,
MdMenuModule,
MdIconModule
]
})
export class MaterialModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: MaterialModule,
providers: [
]
};
}
}
(this is a reproduction of my post here because the two issues are really the same)
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.
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.
Modified 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]
};
}
}
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.
The details of this implementation can be seen here.
This limitation of ng-Material Modules is slotted to be fixed with the alpha 8 release