Feather icons usage in Vue.JS

Viewed 12968

I've been trying to use feather-icons in a new vue project. I first initialized the project using the vue-clie tools:

vue init webpack

once done, I ran:

npm install
npm run dev

After that I installed feather-icons through npm as follows:

npm install --save feather-icons

Once done, I tried using the icons by importing the module in my main.js file:

main.js:

import 'feather-icons'

import Vue from 'vue'
import App from './App'
import router from './router'

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,
  template: '<App/>',
  components: {
    App
  }
})

Then I tried using an icon in a Hello component:

Hello.vue:

<template>
  <div>
    <h1> Hello World!</h1>
    <i data-feather="flag"></i>
  </div>
</template>

<script>
  export default {
    name: 'hello',
    data() {
      return {
        msg: 'Welcome to Your Vue.js App'
      }
    }
  }

</script>
<style>
</style>

No error is detected during execution, yet the icon set refuses to work. I've tried including the feather-icons directly on the index.html file, but the problem persists.

I'm guessing whatever is causing this is related to the data-feather attribute on the i tag required to invoke feather-icons.

I've been at it for almost a couple hours, but nothing I tried seems to work. Any help would be appreciated. Thanks.

UPDATE 1: As per @yuriy636's suggestion, I imported feather-icons in my App component then called feather.replace() in mounted:

App.vue:

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

<script>

  import feather from 'feather-icons'

  export default {
    name: 'app',

    mounted() {
      feather.replace();
    }
  }

</script>

<style>
</style>

UPDATE 2:

As pointed out by @smarx, there is a module named vue-feather-icons that facilitates the usage of feather-icons with vue. just install it, import it and use it. This seems to have solved the issue.

2 Answers

This can also be done as a functional component, and you can use the icon-names to simply pick which svg to render.

You can also swap out feathers and use another svg-sprite

// Usage    
    <div class="flex items-center p-2 mt-2 bg-white">
      <x-svg icon="log-out" class="w-4 h-4" />
    </div>

 // x-svg.vue
    <template functional>
      <svg
        fill="none"
        :viewBox="props.viewBox"
        :class="['stroke-' + props.stroke, data.class, data.staticClass]"
        class="inline-flex w-4 h-4 text-gray-500 stroke-current hover:text-gray-900 group-hover:text-gray-900"
        stroke-linecap="round"
        stroke-linejoin="round"
        :ref="data.ref"

        :style="[data.style, data.staticStyle]"
        v-bind="data.attrs"
        v-on="listeners"
      >
        <use :href="require('@/assets/img/feather-sptite.svg') + '#' + props.icon" />
      </svg>
    </template>

    <script>
    export default {
      props: {
        icon: {
          type: String,
          default: 'alert-circle'
        },
        stroke: {
          type: Number,
          default: 1,
          validator(v) {
            const sizes = [0.5, 1, 1.5, 2, 2.5]
            return sizes.includes(v)
          }
        },
        viewBox: {
          type: String,
          default: '0 0 24 24'
        }
      }
    }
    </script>
Related