Replace mat-icon with SVG graphic

You can use angular-svg-icon

The angular-svg-icon is an Angular 7 service and component that provides a means to inline SVG files to allow for them to be easily styled by CSS and code.

The service provides an icon registery that loads and caches a SVG indexed by its url. The component is responsible for displaying the SVG. After getting the svg from the registry it clones the SVGElement and the SVG to the component's inner HTML.

For more information: https://www.npmjs.com/package/angular-svg-icon


Unfotunatley this does not exactly solve your problem, because you will need to use the argument svgIcon on the mat-icon element instead of using the innerText of mat-icon but otherwise it works:

  1. You have to allow to angular to import from svg's by declaring the module.
  2. To import/inline the icons into javascript, you will have to override the loader. This can be achieved through using the raw-loader.
  3. Now you will be able to import the svg into angular and register them through the MatIconRegistry;

As an example:

// src/typings.d.ts

declare module '*.svg' {
  const svg: string;
  export default svg;
}
// src/app/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { DomSanitizer } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { MatIconModule, MatIconRegistry } from '@angular/material';

import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';

import thumbsUp from '!!raw-loader!./thumbs-up.svg';

@NgModule({
  imports:      [ 
    BrowserModule, 
    FormsModule, 
    MatIconModule 
  ],
  declarations: [ AppComponent, HelloComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule {
  constructor(iconRegistry: MatIconRegistry, sanitizer: DomSanitizer) {
    iconRegistry.addSvgIconLiteral(
        'thumbsUp', sanitizer.bypassSecurityTrustHtml(thumbsUp));
  }
}
// src/app/app.component.html
<mat-icon svgIcon="thumbsUp"></mat-icon>
// src/app/thumbs-up.svg
<svg>...</svg>

Another approach would be to install @mdi/svg

npm install @mdi/svg

and then follow the steps above, with the difference to import each necessary icon as well, e.g. expand_more and chevron_right

so in src/app/app.module.ts

// src/app/app.module.ts
...
import expandMore from '!!raw-loader!@mdi/svg/svg/chevron-down.svg';
import chevronRight from '!!raw-loader!@mdi/svg/svg/chevron-right.svg';
...
export class WeddingDayModule {
  constructor(
    private iconRegistry: MatIconRegistry,
    private sanitizer: DomSanitizer
  ) {
    iconRegistry
      .addSvgIconLiteral('chevron_right', sanitizer.bypassSecurityTrustHtml(chevronRight))
      .addSvgIconLiteral('expand_more', sanitizer.bypassSecurityTrustHtml(expandMore));
  }
 }

And in the html just as a simplification... but you will get the idea...

//src/app/app.component.html
...
<mat-icon [svgIcon]="expanded ? 'chevron_right' : 'expand_more'" (click)="expanded = !expanded"></mat-icon>
...

the down side with this approach is, that you will have to register all the icons you want to use... But at least you stay in the same domain of change. Instead of using the ligatures you can change them all through the svgIcon and you get more icons than just the icons the outdated material-design-icons library holds.

I hope that helps