How to: Use Angular Material’s Mat-Icon with local SVG Images?

Duncan Faulkner
ngconf
Published in
6 min readJan 20, 2021

Duncan Faulkner
Jan 20 - 2021

When developing an Angular application with Angular Material, there comes a point when we need to add icons on our components, or buttons etc… Angular Material has the Mat-Icon component for doing this. This component works with web fonts like Font-Awesome for instance, simply by adding the name of the image required and an image is displayed.

Note: Requires an Angular application with Angular Material installed and configured with a reference to Font-Awesome library.

But what about if you have custom icons that are not part of a web font? And would like to makes changes to the icon, for example: change the colour on hover or on a specific condition at run time?

In a recent project I had a bespoke set of SVG icons, the Angular web application was to be installed on a server that didn’t have access to the internet, so the images had to be local. I wanted to use the Mat-Icon component out of the box. I still wanted to be able to change the colours of the icons at various stages throughout the application based on certain conditions as well as on hover. This post covers how I achieved that.

SVG Icons

There are a number of different ways to register an icon with the Mat-Icon component, this post discusses addSvgIcon, the others are addSvgIconInNamespace,
addSvgIconLiteral,
addSvgIconLiteralInNamespace
and are all methods of MatIconRegistry.

Setting up an Angular project

In the newly created Angular project, create a shared directory and add a new file named material.module.ts. I like to separate Angular Material imports into their own module. I will also create a separate module for other 3rd party components, this just makes it easier to import later, especially using the NX console utility.

Material Module

MatIconModule is the module for the component, and the MatIconRegistry is a service to register and display icons. Don’t forget to export it as well, otherwise it won’t be available and Angular will not know anything about the Angular Material components. Then add a reference to the material.module.ts in the app.module.ts.

app module

Now we have the Angular Material components set up and configured we need to register the icons, before we can use them. For the moment we are just going to add these to the app.component.ts to get up and running, we’ll look at a better method later on.

component — first example

Add this to the app.component.html page, we’ll discuss this in more detail in a bit.

component — first example html

At this point we are not going to see much in the browser as we have an issue with the image URL. If you open the browsers console section, you will see the following error:

Error: unsafe value used in a resource URL context.

So what does this error mean? A brief explanation from the Angular Material website says:

To prevent an Cross Site Scripting (XSS), SVG URL’s and HTML strings passed to MatIconRegistry must be marked as trusted by the Angular’s DomSanitizer service. Icons are fetched via XmlHttpRequest and must have their URL’s on the same domain as the containing page or configured to allow cross-domain access.

So lets add the DomSanitizer and fix this issue.

component — second example with dom sanitizer

The call to bypassSecurityTrustResourceUrl takes a URL as a parameter and sanitises it so that an attacker cannot inject a ‘JavaScript:` URL for example, see official documentation on DomSanitizer. Now that we have this in place, we should now see two icons in the browser.

If we have a lot of icons to add this means lots of typing and lots of repetitive code, so let's refactor this some more. Start by removing all of this code (including the constructor) from the app.component.ts. This shouldn’t really be in the app.component.ts file. Let's create another new module in the shared directory and call it icon.module.ts and then add the following:

component — third example

Overall, that’s not too bad. We are only writing out the domSanitizer code once in the private method but more importantly, all the code is out of the app.component.ts file and is now a self-contained module. If there are a lot of icons to add then this file will get a bit long, but the typing has gotten shorter (well, a little shorter at least).

Note: Don’t forget to add this new icon.module.ts to the app.module.ts otherwise it won’t work.

Using the Mat-Icon component

So how do we use the mat-icon component? As seen earlier in this post we add the following code to our app.components.html page.

This is a very simple example showing how to put a home and an add icon on a page/component. This is not too dissimilar to how we would use this component with web fonts, but we are now using the svgIcon input property. The value we give to this input is the first parameter used in our call to register the .addSvgIcon(‘home’, …) in this case home.

Now we have an icon in place, how do we change the colour of the icon when someone hovers over it for example?

Change the icon colour

A Home icon. Example icon copy this into a file with the SVG extension.

svg icon

In the above XML, I’ve removed all the namespaces etc… The main part here is the fill=”#00FFFF”. This sets the colour for the image, in this case to AquaMarine.

If the fill=”#00…” property is not there and you want a different colour to the default black, then you can add it to the path as above. It’s optional.

I usually add the fill property and set it to white and then change it, in SCSS as and when required (because this example had a white background, I used another colour).

Add a class to the mat-icon html tag, as above. Next, add the SCSS for the class so that, when a user hovers over the button the colour of the icon changes.

The Icons should now change colour when hovering over them.

Enjoy!

In a future post, we’ll take a look at improving this and refactor to use a service to load the icons.

Now that you’ve read this article and learned a thing or two (or ten!), let’s kick things up another notch!

Take your skills to a whole new level by joining us in person for the world’s first MAJOR Angular conference in over 2 years! Not only will You be hearing from some of the industry’s foremost experts in Angular (including the Angular team themselves!), but you’ll also get access to:

  • Expert panels and Q&A sessions with the speakers
  • A friendly Hallway Track where you can network with 1,500 of your fellow Angular developers, sponsors, and speakers alike.
  • Hands-on workshops
  • Games, prizes, live entertainment, and be able to engage with them and a party you’ll never forget

We’ll see you there this August 29th-Sept 2nd, 2022. Online-only tickets are available as well.

https://2022.ng-conf.org/

--

--