Preston Lamb | ng-conf | Dec 2020
tldr;
In the last couple years, SVG has become the preferred way of displaying icons in web applications. This is because SVGs can be scaled to any size without loss of quality, they can be changed to any color, and they can be animated. These are just a few of the benefits. The downside is that the SVG code is a little hard to manage and deal with in your application. Luckily there are tools to help with this in your Angular apps that make using SVG icons much easier than before.
SVG Icons
There are two ways to include SVG icons in your app. You can place a .svg
image on the page, or the SVG’s XML code. The XML code is what allows you to change the display of the icon, and is my preferred way of doing it. The problem with the XML code method is that you have a big, complicated piece of XML in your HTML that doesn’t tell you what the icon is, and is prone to accidentally being changed. Here’s an example of an SVG icon:
<svg xmlns=”http://www.w3.org/2000/svg" viewBox=”0 0 20 20" fill=”currentColor”>
<path d=”M10.394 2.08a1 1 0 00-.788 0l-7 3a1 1 0 000 1.84L5.25 8.051a.999.999 0 01.356-.257l4–1.714a1 1 0
11.788 1.838L7.667 9.088l1.94.831a1 1 0 00.787 0l7–3a1 1 0 000–1.838l-7–3zM3.31 9.397L5 10.12v4.102a8.969
8.969 0 00–1.05-.174 1 1 0 01-.89-.89 11.115 11.115 0 01.25–3.762zM9.3 16.573A9.026 9.026 0 007 14.935v-
3.957l1.818.78a3 3 0 002.364 0l5.508–2.361a11.026 11.026 0 01.25 3.762 1 1 0 01-.89.89 8.968 8.968 0 00–
5.35 2.524 1 1 0 01–1.4 0zM6 18a1 1 0 001–1v-2.065a8.935 8.935 0 00–2-.712V17a1 1 0 001 1z” />
</svg>
As you can see, that’s a huge piece of XML. What’s worse, you can’t tell what it does just by looking at it. And what happens if a small part of it is accidentally deleted? There’s gotta be a better way to deal with it, right? Well, lucky for us there is.
I recently discovered a library on NPM called angular-svg-icon
that allows you to load the SVG code from above into a service and then output the icon by name in your template with an Angular element. This is the process:
// app.component.ts
export class AppCompnent {
constructor(private _registry: SvgIconRegistryService) {}
ngOnInit() {
this._registry.addSvg(‘academic-cap’, ‘…SVG CODE…’);
}
}
This code snippet imports the SvgIconRegistryService
from angular-svg-icon
and declares a new SVG icon called academic-cap
that you can use in your template, like this:
<svg-icon name=”academic-cap”></svg-icon>
That will output the SVG onto the screen wherever you want. You can style the SVG by using the svgClass
input:
<svg-icon name=”academic-cap” svgClass=”bg-red-400 h-20 w-20" ></svg-icon>
This method drastically improves the ease of using SVG icons in your application. But there’s one more improvement that can be made with the angular-svg-icon-preloader
library. This library is meant to be used in conjunction with angular-svg-icon
and will load SVG icons from a JSON file when your app bootstraps. This way you don’t need to muddy your AppComponent
file to load several frequently-used icons. The service will just load all the icons for you automatically, and then you can use them in your templates as shown above. You can load the SVG data or SVG image files, whichever one you would prefer. Here’s how the JSON file should be created:
// icons.json
{
"iconImageFiles": [
{
"iconName": "badge-check",
"iconPath": "/assets/icons/badge-check.svg"
}
],
"customIcons": [
{
"iconName": "academic-cap",
"iconData": "<svg xmlns=\"http://www.w3.org/2000/svg\" > <path d=\"...\" /> </svg>"
}
]
}
There are two array attributes as part of the JSON file, iconImageFiles
and customIcons
. The items in these arrays both have an iconName
attribute, and then either iconPath
, which is a path to the SVG file for the icon, or iconData
, which is the SVG’s XML data. When your app bootstraps, these icons will be loaded for you. Just place the JSON file somewhere in your app where it can be accessed when the app is running, like the assets
folder, and then tell the app where it’s located when importing the AngularSvgIconPreloaderModule
:
// app.module.ts
@NgModule({
imports: [
AngularSvgIconModule.forRoot(),
AngularSvgIconPreloaderModule.forRoot({
configUrl: './assets/json/icons.json',
}),
]
})
In the forRoot
method on the AngularSvgIconPreloaderModule
, provide an object with a configUrl
attribute that has the path to the icons file. That’s all it takes to have the icons preloaded for you in your app. Now, it’s not necessary to load every icon in your app through the JSON file, but at the very least you can load the most used icons. If you still want to load icons in a component with the SvgIconRegistryService
, you can do that too.
Conclusion
After discovering the angular-svg-icon
library, dealing with SVG icons became much easier and convenient. No more random SVG data in my templates, and everyone knows exactly what icon is being used. This will definitely be a common tool in my toolbox from now on.
ng-conf: The Musical is coming
ng-conf: The Musical is a two-day conference from the ng-conf folks coming on April 22nd & 23rd, 2021. Check it out at ng-conf.org
Top comments (1)
I wonder what is better when using the service compared to having a component that stores svg's inside and displays correct one based on a property name?