Angular Icon Registry
In this guide, you will learn how to build a fully functional icon component in Angular from scratch. We will demonstrate how to convert SVG files into TypeScript code and dynamically inject these icons into your HTML. This method avoids image loading delays and ensures full typing, enhancing both the performance and consistency of your application.
Step 1: Install the Required Library
We'll begin by installing the svg-to-ts
package, which will allow us to convert SVG files into a single TypeScript file.
npm install --save-dev svg-to-ts
Step 2: Configure the SVG-to-TypeScript Conversion
Next, create a configuration file svg-to-ts.json
in the root directory with the following content:
{
"conversionType": "object",
"srcFiles": [
"./icons/*.svg"
],
"svgoConfig": {
"plugins": [
"cleanupAttrs"
]
},
"outputDirectory": "./src/app/components/icon",
"fileName": "icon.registry",
"delimiter": "KEBAB",
"typeName": "Icon"
}
Ensure that the configuration is compatible with the installed version of the svg-to-ts
package. The example above is based on version [email protected]
.
Step 3: Add Icons to Your Project
Place all your SVG icons in the icons
directory. If you don't have an icon ready, you can use the following example to practice:
<svg height="16" stroke-linejoin="round" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M14 3H2C1.72386 3 1.5 3.22386 1.5 3.5V5L14.5 5V3.5C14.5 3.22386 14.2761 3 14 3ZM1.5 12.5V6.5L14.5 6.5V12.5C14.5 12.7761 14.2761 13 14 13H2C1.72386 13 1.5 12.7761 1.5 12.5ZM2 1.5C0.895431 1.5 0 2.39543 0 3.5V12.5C0 13.6046 0.895431 14.5 2 14.5H14C15.1046 14.5 16 13.6046 16 12.5V3.5C16 2.39543 15.1046 1.5 14 1.5H2ZM4 10.75C4.41421 10.75 4.75 10.4142 4.75 10C4.75 9.58579 4.41421 9.25 4 9.25C3.58579 9.25 3.25 9.58579 3.25 10C3.25 10.4142 3.58579 10.75 4 10.75Z"
fill="currentColor"/>
</svg>
It's essential that each icon has a fixed size and uses the attribute fill="currentColor"
. This allows the icon to inherit color from its parent element, enabling flexible color styling with CSS.
Step 4: Convert SVG Icons to TypeScript
Run the following command to convert the SVG files to TypeScript:
svg-to-ts-object --config ./svg-to-ts.json
After the process completes, you'll find the output in src/app/components/icon/icon.registry.ts
.
The generated TypeScript file maps icon names to their SVG content,
offering full type checking and reducing the risk of naming errors.
/* 🤖 this file was generated by svg-to-ts */
export default {
card: '<svg height="16" stroke-linejoin="round" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" clip-rule="evenodd" d="M14 3H2C1.72386 3 1.5 3.22386 1.5 3.5V5L14.5 5V3.5C14.5 3.22386 14.2761 3 14 3ZM1.5 12.5V6.5L14.5 6.5V12.5C14.5 12.7761 14.2761 13 14 13H2C1.72386 13 1.5 12.7761 1.5 12.5ZM2 1.5C0.895431 1.5 0 2.39543 0 3.5V12.5C0 13.6046 0.895431 14.5 2 14.5H14C15.1046 14.5 16 13.6046 16 12.5V3.5C16 2.39543 15.1046 1.5 14 1.5H2ZM4 10.75C4.41421 10.75 4.75 10.4142 4.75 10C4.75 9.58579 4.41421 9.25 4 9.25C3.58579 9.25 3.25 9.58579 3.25 10C3.25 10.4142 3.58579 10.75 4 10.75Z" fill="currentColor"/></svg>',
}
Whenever new SVG files are added to the icons folder, rerun the conversion command to update the TypeScript registry.
Step 5: Create the Icon Component
Now, we will create an IconComponent
that will reference the generated icon.registry.ts
file
and dynamically inject the correct icon into the DOM using Angular’s DomSanitizer
.
<!-- leave this file empty -->
src/app/components/icon/icon.component.scss:host {
display: block;
box-sizing: border-box;
user-select: none;
color: #222;
width: 16px;
height: 16px;
&::ng-deep svg {
display: block;
box-sizing: border-box;
height: inherit;
width: inherit;
color: inherit;
transition: color .3s cubic-bezier(0.645, 0.045, 0.355, 1);
path {
color: inherit;
}
}
}
src/app/components/icon/icon.component.tsimport {DomSanitizer, SafeHtml} from '@angular/platform-browser';
import {Component, computed, inject, input} from '@angular/core';
import {default as icons, type Icon} from "./icon.registry";
@Component({
selector: 'app-icon',
templateUrl: './icon.component.html',
styleUrl: './icon.component.scss',
host: {
'[innerHTML]': 'svg()',
},
})
export class IconComponent {
public readonly name = input.required<Icon>();
public readonly svg = computed<SafeHtml>(() => {
return this.domSanitizer.bypassSecurityTrustHtml(icons[this.name()]);
});
private readonly domSanitizer = inject(DomSanitizer)
}
Remember to include the IconComponent
in your application's module declarations.
Step 6: Use the Icon Component
You can now use the icon component in your templates as follows:
<app-icon name="card" />
Step 7: Customizing Icon Styles
To customize the size or color of the icons, you can override the styles of the app-icon
component as needed:
app-icon {
color: red;
width: 40px;
height: 40px;
}
By following this approach, you gain the benefits of TypeScript's IntelliSense, reducing the likelihood of errors, while also enabling flexible style overrides and instant icon loading across your Angular application.