NativeScript + Angular: Icons as a service
I have a hard time imagining a mobile app without icons. Whether used as companions to text or as a complete replacement, icons communicate the intent of a feature to users.
Setting up icon fonts in NativeScript + Angular applications is outlined in the docs, and you end up with something like this.
<Label text=”” class=”far”></Label>
Why change this?
Seems simple enough. It’s a one liner and not all that complicated. Why change it?
- I don’t have a clue what icon that is. I want to be able to declare that I want to use the
home
icon, not
. - It’s dependent on setting the class to use the icon font. Because it’s the same every time, we can abstract that way.
- It feels weird to use a
Label
withtext
to get an icon. 🤷♂️
Enter the <app-icon> component
Instead, I’d rather abstract that ugliness away into a component with an API something more like…
<app-icon name="home"></app-icon>
It’s a multistep process to get there responsibly. First, an IconService
to perform the transformation from the icon name I ask for to the character code string the Label
needs.
import { Injectable } from "@angular/core";import { ICON_MAP } from "./icon.map";@Injectable({ providedIn: "root"})export class IconService { public get(name: string): string { try { return String.fromCharCode(ICON_MAP[name]); } catch(e) { return ''; } }}
This service is part of the CoreModule
, which is imported to the AppModule
and never any other module. Meaning it’s a singleton and only ever instantiated once. This is important because the IconComponent
is part of the SharedModule
which is imported into every module except the AppModule
.
import { Component, OnInit, Input } from "@angular/core";import { IconService } from "~/app/core/icon/icon.service";@Component({ selector: "app-icon", template: ` <Label [text]="iconString" class="ico"></Label> `, styles: [], moduleId: module.id})export class IconComponent implements OnInit { @Input() name: string; public iconString: string; constructor(private _iconService: IconService) {} ngOnInit() { this.iconString = this._iconService.get(this.name); }}
Thoughts
Things like this seems small. After all, it was just one line and this solution adds infrastructure to the application that will have to be managed/maintained over time.
The result though, is a more intuitive and error resistant API for using icons. Code bases that focus on these small improvements are fun to work in and enhance productivity.