Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace mat-icon with SVG graphic

Angular newbie here..could someone direct me to the right way how could I replace the existing Material icons with custom ones properly, more precisely with the SVG graphics? Something like this:

So this:

<mat-icon class="mat-icon-rtl-mirror">
     {{nestedTreeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
</mat-icon>

With this:

<mat-icon class="mat-icon-rtl-mirror">
     {{nestedTreeControl.isExpanded(node) ? 'INSERT_SVG_1_HERE' : 'INSERT_SVG_2_HERE'}}
</mat-icon>
like image 515
Smithy Avatar asked Mar 22 '19 11:03

Smithy


People also ask

Can SVG file be used as icon?

Scalable Vector Graphics, or SVGs, are a generally a good choice for use as icons on your website, because they are vector graphics. Vector graphics can be scaled to any size without losing quality. The files are small and compress well, so they won't make your website slow to load.

How do I add an SVG icon?

SVG images can be written directly into the HTML document using the <svg> </svg> tag. To do this, open the SVG image in VS code or your preferred IDE, copy the code, and paste it inside the <body> element in your HTML document. If you did everything correctly, your webpage should look exactly like the demo below.

How do I create a custom SVG icon?

There are two ways to create SVG icons: by hand or using a tool. The latter is the easier option that involves practically no code. When you're using a vector image program, you draw your icons on a virtual drawing board using different shapes, colors, and path manipulation. Then you export your .


2 Answers

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

like image 121
Stack Overflow Avatar answered Oct 12 '22 08:10

Stack Overflow


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

like image 41
Eydrian Avatar answered Oct 12 '22 09:10

Eydrian