Icon Hints on INPUT fields using AngularJS

Note: this was originally published in a now-defunct Medium-post back in 2014. It’s been re-edited for 2020 audiences 🤖.

🌎 We will learn how to make input fields that require an ISO 3166-1 country value to display the corresponding flag, in much the same way Bootstrap shows icons for validations states.

Custom Directive - Final Result

Finding usable country flags

Boostrap can use custom icons but this is not quite what I needed since I had all my images in separate files and I didn’t want to combine them into a single one using the sprite generator in the tutorial, nor did I want to generate a custom class for flags I may not even need. What to do….what to do…? 👉 FamFamFam Flags, bingo!

Creating a generic custom class

The custom icons tutorial above already shows how to create our own custom classes to handle this, so why not generalize them? I ended up with this after tweaking pixels and margins:

Simple CSS+Angular

And voilà! now let’s just add our generic custom class in addition to form-control-feedback and indicate where the image is supposed to come from by decorating the style attribute with the runtime country-specific value of the flag:

Wrapping it with a Custom Directive

The above will work, but you will have to do a lot of copy/paste if you want to reuse it, let’s create a directive to tuck away all the html and css.

We are indicating that when we invoke our directive, we will tell it where to try to “guess” the value from via the countryValueFrom attribute. Now, let’s move the <input> and <span> into its own .html file, and instead of the original {{expression}} let’s use the countryValueFrom parameter we indicated in the directive code:

Let’s try it with a static value:

Custom Directive - Static Value Output

It worked!

Now let’s see if it can dynamically use the value from the <input name="country"> generated by the directive:

Custom Directive - User Input driven. Broken

🤔??, well, country does not exist in the invoking $scope, it only exists in the directive’s isolate scope. Therefore let’s change our directive to accept a field name and use that to generate our input field. While we’re at it let’s parameterize other currently-hard-coded values, and use defaults when not specified.

Let’s try changing the placeholder and see the result:

Custom Directive - Scope Driven

Final refactorings and optimizations

Now, let’s make our directive be usable not only as an HTML element, but invokable via attribute tagging or via class name:

  • We need to add a root element to our HTML template, it’s a requirement when using replace:true
  • We update our restrictions to A-ttribute and C-lass
  • Simplify our directive attributes, unify it all under “name”

Code we can easily use everywhere in our app:

Custom Directive - Final Result