DEV Community

loading...
Cover image for Managing SVG Icons in Your Angular App

Managing SVG Icons in Your Angular App

ngconf profile image ng-conf ・4 min read

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>
Enter fullscreen mode Exit fullscreen mode

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…’);
  }
}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

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',
    }),
  ]
})
Enter fullscreen mode Exit fullscreen mode

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

Discussion (1)

Collapse
tomaszs2 profile image
Tomasz Smykowski

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?

Forem Open with the Forem app