• Home

  • Custom Ecommerce
  • Application Development
  • Database Consulting
  • Cloud Hosting
  • Systems Integration
  • Legacy Business Systems
  • Security & Compliance
  • GIS

  • Expertise

  • About Us
  • Our Team
  • Clients
  • Blog
  • Careers

  • VisionPort

  • Contact
  • Our Blog

    Ongoing observations by End Point Dev people

    Vue, Font Awesome, and Facebook/​Twitter Icons

    David Christensen

    By David Christensen
    July 12, 2018

    some Font Awesome fonts

    Overview

    Font Awesome and Vue are both great technologies. Here I detail overcoming some issues when trying to get the Facebook and Twitter icons working when using the vue-fontawesome bindings in the hopes of saving others future debugging time.

    Detail

    Recently, I was working with the vue-fontawesome tools, which have recently been updated to version 5 of Font Awesome. A quick installation recipe:

    $ yarn add @fortawesome/fontawesome
    $ yarn add @fortawesome/fontawesome-svg-core
    $ yarn add @fortawesome/free-solid-svg-icons
    $ yarn add @fortawesome/free-brands-svg-icons
    $ yarn add @fortawesome/vue-fontawesome
    

    A best practice when using Font Awesome is to import only the icons you need for your specific project instead of the thousand+, as this just contributes to project bloat. So in our main.js file, we import them like so:

    // Font Awesome-related initialization
    import { library } from '@fortawesome/fontawesome-svg-core'
    import { faEnvelope, faUser } from '@fortawesome/free-solid-svg-icons'
    import { faFacebook, faTwitter } from '@fortawesome/free-brands-svg-icons'
    import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
    
    // Add the specific imported icons
    library.add(faEnvelope)
    library.add(faUser)
    library.add(faFacebook)
    library.add(faTwitter)
    
    // Enable the FontAwesomeIcon component globally
    Vue.component('font-awesome-icon', FontAwesomeIcon)
    

    This allows you to include icons in your view components like so:

    <template>
      <div class="icons">
        <font-awesome-icon icon="user"/>
        <font-awesome-icon icon="envelope"/>
      </div>
    </template>
    

    This worked fine for me until I tried to use the facebook and twitter icon:

    <template>
      <div class="icons">
        <font-awesome-icon icon="user"/>
        <font-awesome-icon icon="envelope"/>
        <font-awesome-icon icon="twitter"/>  <!-- broken -->
        <font-awesome-icon icon="facebook"/> <!-- broken -->
      </div>
    </template>
    

    Only blank spots and errors in the browser console like so:

    [Error] Could not find one or more icon(s) (2)
    {prefix: "fas", iconName: "twitter"}
    {}
    [Error] Could not find one or more icon(s) (2)
    {prefix: "fas", iconName: "facebook"}
    {}
    

    After turning up dry from a run to the Google well and scanning the docs, I determined that this must come down to a difference in the prefix; since the icons that worked were being imported from the free-solid-svg-icons library, it would seem that that was the source of the fas prefix. Since the non-working icons were coming from the free-brands-svg-icons library it stood to reason that somehow passing in a prefix parameter of fab would work.

    I tested modifying things like follows, just to exercise potentially obvious answers. Sadly, this did not result in workage.

    <template>
      <div class="icons">
        <font-awesome-icon icon="user"/>
        <font-awesome-icon icon="envelope"/>
        <font-awesome-icon icon="twitter" prefix="fab"/>  <!-- still broken -->
        <font-awesome-icon icon="fab-facebook"/>          <!-- also still broken -->
      </div>
    </template>
    

    I finally took to the original source for the FontAwesomeIcon component (every engineer’s favorite thing, aside from brown paper packages tied up with string), and noted the following:

    function normalizeIconArgs (icon) {
      if (icon === null) {
        return null
      }
    
      if (typeof icon === 'object' && icon.prefix && icon.iconName) {
        return icon
      }
    
      if (Array.isArray(icon) && icon.length === 2) {
        return { prefix: icon[0], iconName: icon[1] }
      }
    
      if (typeof icon === 'string') {
        return { prefix: 'fas', iconName: icon }
      }
    }
    

    AHA! The icon parameter is what was passed in in the <font-awesome-icon> component, so I immediately attempted to utilize an object to pass the prefix and the iconName parameter (since this is the name in the object referenced here, it should be the key).

    So I ended up trying:

    <template>
      <div class="icons">
        <font-awesome-icon icon="user"/>
        <font-awesome-icon icon="envelope"/>
        <font-awesome-icon :icon="{ prefix: 'fab', iconName: 'twitter' }"/>
        <font-awesome-icon :icon="{ prefix: 'fab', iconName: 'facebook' }"/>
      </div>
    </template>
    

    (I am omitting the part where I stupidly left out the leading : to pass in an explicit object instead of a string equivalent.)

    Everything worked! And there was much rejoicing! Hope this helps someone else who had the same issue as me.

    vue javascript


    Comments