A NativeScript Font Icon Converter


Getting set up to use Icon Fonts in a NativeScript app is fairly straight-forward. NativeScript documentation covers it, and Nathanael Anderson has a tutorial covering things in more depth. However, there's one annoyance I have with using them in NativeScript and this post will cover that and one way to resolve it.


The Annoyance

Once you're set up to use icon fonts, you'll typically have a CSS rule defined to set the font-family when a certain class is used:

.fa {
  font-family: FontAwesome;
}

But, as you can see in the above referenced getting started docs/tutorial, CSS is not what sets the content as it would be if we were using HTML and Icon Fonts. We have to find the unicode and set the text property of our element to use that:

<Label class="fa" text="\uf293" />  

So you must either memorize the unicode for your font icons or be resigned to looking them up every time.


One solution

NativeScript has a feature baked into it called Converters - essentially functions you can pipe an input to and have it converted to a different output without changing the source (i.e. a property on a model). You can also have application-wide converters by adding them to your application's resources, which is what we'll be using to make it easier to use our icon fonts!.

Create our Converter Function

The first thing we'll want to do is to create the function that will be our converter. Let's create a new directory: app/utils/ and create a new TypeScript file within named fontIconConverter.ts. This converter is actually really simple - it just has a hash map of all the icons we want to use and their unicode value, then provides a function for converting strings, or parts of strings, to the appropriate unicode value. Notice below that we're also handling cases where an icon may be passed in within a string of text.

// app/utils/fontIconConverter.ts
const fontToUnicode = {  
  //I recommend using the full css class name of the icon (i.e. 'fa-bluetooth') 
  //  instead of shortening (i.e. just 'bluetooth') in case you need to use the 
  //  text along side an icon
  'fa-bluetooth': '\uf293',
  'fa-hashtag': '\uf292',
  'fa-usb': '\uf287'
};

function valueToFontUnicode(value: string): string {  
  //if the value isn't a key in our hash map, just return the value as it is
  return fontToUnicode[value] || value;
}

export default function fontIconConverter(value: string): string {  
  //check for spaces so we can handle things like "fa-bluetooth some text here"
  if (/\s/.test(value)) {
    return value.split(/\s/).map(t => valueToFontUnicode(t)).join(' ');
  } else {
    return valueToFontUnicode(value);
  }
}

Make the converter accessible application-wide

Now that we've defined a converter function, we just need to add it to our application resources to make it available application-wide. Simply navigate to your app/app.ts file, and make the following additions:

import fontIconConverter from './utils/fontIconConverter';  
application.resources['fontIconConverter'] = fontIconConverter;  

Use the converter in your view

Now that we've added the converter to our application resources, we can use it in any view like this:

<Label class="fa" text="{{ 'fa-bluetooth (bluetooth icon)' | fontIconConverter }}" />  

Is it still clunky/ugly? Yep. But, I find it easier to remember the actual names of the icons over their unicode values. So, in an app where a lot of different icons are being used, this may just be helpful. If you're only using one or two icons then maybe it wouldn't be worth it - you'd have to decide :)

Quick Caveat

Any time that you are using the binding syntax {{ ... }} your view must have a binding context or it won't interpolate. Even if all you're doing is taking a static string, such as is the case with the font icon converter, and running it through a converter. If needed, you can just set the binding context to an empty object and that works, but kinda feels hacky to me.


It's certainly not a perfect/elegant solution, but as far as I can find it's either typing in the unicode directly to the label or some converter like this when it comes to using font icons. If you know of a better approach, feel free to share in the comments!

-Bradley

Loading Google+ Comments ...