This is a tiny, but useful post that will demonstrate how to create a service that registers custom svg icons in order to use them through the mat-icon component.
Step 1. I place all my icons under assets/svg/icons
Step 2. I create an string enum with all the icon names i.e. (you could just have a string array but I like the idea of using an enum)
export enum Icons {
Close = 'close',
Done = 'done',
Edit = 'edit'
}
Step 3. I create my service. Which simply iterates all values in my string enum and registers them again the MatIconRegistry
. bypassSecurityTrustResourceUrl
simply bypass the security checks and trusts the svg file (make sure the svgs are to be trusted).
@Injectable({
providedIn: 'root'
})
export class IconService {
constructor(
private matIconRegistry: MatIconRegistry,
private domSanitizer: DomSanitizer
) { }
public registerIcons(): void {
this.loadIcons(Object.values(Icons), '../assets/svg/icons');
}
private loadIcons(iconKeys: string[], iconUrl: string): void {
iconKeys.forEach(key => {
this.matIconRegistry.addSvgIcon(key, this.domSanitizer.bypassSecurityTrustResourceUrl(`${iconUrl}/${key}.svg`));
});
}
}
Step 4. Then simply on the app.component.ts
ngOnInit call the registerIcons
function
constructor(private iconService: IconService) {
}
ngOnInit() {
this.iconService.registerIcons();
}
Step 5. Use them anywhere in the application
<mat-icon svgIcon="edit"></mat-icon>
Top comments (9)
Thanks for the guide. It worked great. I have another question about coloring the icons. I know we can color SVG using CSS fill property. But when I try it is not happening.
The path inside SVG has its own fill set to a different color. The CSS color only works if I remove the fill from that path. I thought the SVG spec says that CSS color will override SVG's. Or should I strip the color info from SVG before using it?
Were you able to achieve this functionality?
Yes. I had to override the fill color on each path, circle with CSS.
But this would load ALL icons at once, right? Also for lazy loaded modules?
No, this service registers the icons, it doesn't load any of them, until the view ultimately requests for one.
But yes, it registers all icons regardless if they are used or not.
and its quite easy to see that, if you create an interceptor and log all requests going through it, you will see requests on the svg files only when the view requests them.
What side effects does the registration have?
I am concerned about loading times and registration should not have a lot of impact to it. It feels somewhat wrong to register them globally and not only per lazy loaded module.
I don't think there is match of an impact since the only thing that addSvgIcon does is add an entry on a Map Object.
github.com/angular/components/blob...
You can always create a method that registers icons on demand. Personally, I don't think you will gain much by doing that, apart from over complicating your solution.
Hello Stefanos, nice article
I am having trouble to use custom icons, when I follow step you provided, it is making a request like this: localhost:4201/icon/repair.svg
and giving 404 response
well first of all the icons by default are supposed to be located under assets, except if you have a custom configuration under angular.json, which defines your assets under a different folder.
the assets (icons in this place need to be referenced from the place they are being accessed)