You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何全局注册Angular Material自定义图标(支持懒加载模块)

Global Registration of Custom SVG Icons in Angular Material for Lazy-Loaded Modules

Great question! The issue you're facing is super common when working with lazy-loaded modules and Angular Material's icon registry. Registering icons in your AppComponent works for eager-loaded components, but lazy modules either can't access the icons (due to path inconsistencies) or force you to repeat the registration code unnecessarily. Here are two clean, scalable fixes:

Solution 1: Use a Root Service for One-Time Icon Registration

Creating a singleton service provided in the root ensures your icons are registered once at app startup, making them available to every module—lazy or eager.

Step 1: Build the Custom Icon Service

import { Injectable } from '@angular/core';
import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';

@Injectable({ providedIn: 'root' })
export class CustomIconService {
  constructor(
    private matIconRegistry: MatIconRegistry,
    private domSanitizer: DomSanitizer
  ) {
    // List all your custom icon names here
    this.registerIcons(['user-profile', 'settings', 'dashboard', 'notification-bell']);
  }

  private registerIcons(iconNames: string[]): void {
    iconNames.forEach(name => {
      this.matIconRegistry.addSvgIcon(
        name,
        // Use an absolute path to avoid location-based errors
        this.domSanitizer.bypassSecurityTrustResourceUrl(`/assets/custom-icons/${name}.svg`)
      );
    });
  }
}

Step 2: Initialize the Service

To trigger the service's icon registration when your app starts, inject it into your AppComponent (you don't even need to use it directly—just injecting it runs the constructor):

import { Component } from '@angular/core';
import { CustomIconService } from './services/custom-icon.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent {
  constructor(private customIconService: CustomIconService) {}
}

For even more control, use APP_INITIALIZER in your AppModule to register icons before the app fully loads:

import { NgModule, APP_INITIALIZER } from '@angular/core';
import { CustomIconService } from './services/custom-icon.service';

export function initializeIcons(service: CustomIconService) {
  return () => service.registerIcons(['user-profile', 'settings', 'dashboard', 'notification-bell']);
}

@NgModule({
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: initializeIcons,
      deps: [CustomIconService],
      multi: true
    }
  ]
})
export class AppModule {}

Solution 2: Create a Shared Icon Module

If you prefer a module-based approach, build a shared module that handles icon registration and exports MatIconModule for reuse across your app.

Step 1: Build the Shared Module

import { NgModule } from '@angular/core';
import { MatIconModule, MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';

@NgModule({
  imports: [MatIconModule],
  exports: [MatIconModule] // Export so other modules can use MatIcon components
})
export class CustomIconsModule {
  constructor(
    private matIconRegistry: MatIconRegistry,
    private domSanitizer: DomSanitizer
  ) {
    const icons = ['user-profile', 'settings', 'dashboard', 'notification-bell'];
    icons.forEach(name => {
      this.matIconRegistry.addSvgIcon(
        name,
        this.domSanitizer.bypassSecurityTrustResourceUrl(`/assets/custom-icons/${name}.svg`)
      );
    });
  }
}

Step 2: Import the Module Everywhere

Add CustomIconsModule to your AppModule and all lazy-loaded modules. Since Angular modules are singletons, the icon registration runs only once—no more redundant code!

Critical Fix: Ditch Relative Paths

Notice we replaced your relative path (../../../assets/...) with an absolute path (/assets/...). Relative paths break when lazy modules are stored in deeper directories, because they rely on the component/module's file location. Absolute paths ensure the icon is always loaded from the correct root folder, regardless of where the component lives.

Either solution will eliminate the need to re-register icons in lazy modules and keep your code clean and DRY.

内容的提问来源于stack exchange,提问作者NathanCaleWichman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 15:27:36