Angular Material and semantic icon identifiers

What we have:
- Angular Material project,
- with one or more icon libraries included as dependencies,
- maybe some custom icons and/or icon fonts added as assets,
- and icons used like this:
<span class="material-icons">arrow_circle_down</span>
<mat-icon fontSet="fa" fontIcon="fa-trash”></mat-icon>
<mat-icon fontSet=“custom-iconfont”>R</mat-icon>
- and if you pass icons around as parameters to your components, things can get ugly:
export interface MenuItem {
caption: string;
link: string;
fontSet?: string;
fontIcon?: string;
iconContent?: string;
}
What we want to have:
- semantically meaningful and uniform way to refer to icons in our code,
- using single string as an identifier, e.g. in template:
<mat-icon fontIcon="add-to-basket"></mat-icon>
- or in TypeScript:
export interface MenuItem {
caption: string;
link: string;
icon: string;
}
How to achieve that:
- assign meaningful names to all icons in the app,
- add all of them to a single CSS “namespace”,
- make that “namespace” a default one for
<mat-icon>
.
And now step-by-step, using Font Awesome and SCSS as an example:
- Add
npm
package:
npm i -D @fortawesome/fontawesome-free
2. Add new entry to all asset
sections of angular.json
:
"assets": [
{
"glob": "**/*",
"input": "./node_modules/@fortawesome/fontawesome-free/webfonts/",
"output": "./assets/fa"
}
]
3. Import Font Awesome source into main project stylesheet (or create a separate file with and then import it from src/style.scss):
@import '~@fortawesome/fontawesome-free/scss/fontawesome', '~@fortawesome/fontawesome-free/scss/solid';$fa-font-path: "../assets/fa";
4. Define your icons using nice, descriptive names which are relevant to your app, and place them into some “namespace”:
.your-namespace {
&.add-new-item {
@extend .fa, .fa-plus;
} &.remove-item {
@extend .fa, .fa-trash;
}
}
5. Repeat steps 1–4 for any other icon set you need to use, be it some NPM package, or icon font provided by designer. (Note: if your icons are provided as .svg
files, you can combine them into a single font, using tools like https://icomoon.io/app/.)
6. Make that namespace default, e.g. from AppModule
:
class AppModule {
constructor(registry: MatIconRegistry) {
registry.setDefaultFontSetClass(‘your-namespace’);
}
}
7. And now you can use it in templates like this:
<mat-icon fontIcon="add-new-item"></mat-icon>
And I think that looks good.