I am trying to toggle a font awesome icon based on a boolean value but it seems that the font-awesome icon remains on the screen after it is drawn:
https://jsfiddle.net/50wL7mdz/200312/
HTML:
<script src="https://unpkg.com/vue"></script>
<script defer src="https://use.fontawesome.com/releases/v5.0.8/js/all.js" integrity="sha384-SlE991lGASHoBfWbelyBPLsUlwY1GwNDJo3jSJO04KZ33K2bwfV9YBauFfnzvynJ" crossorigin="anonymous"></script>

<div id="app">
<input v-model="marked" type="checkbox"/>
<i v-if="marked" class="far fa-check-square"></i>
</div>
JS:
new Vue({
el: '#app',
data: {
marked: false
}
})
Am I doing something wrong or is there a bug in font-awesome or vue.js?
For some reason, you need to wrap the i
tag twice. For example, instead of this:
<div v-if="condition">
<i class="fal fa-caret-left"></i>
</div>
<div v-else>
<i class="fas fa-caret-left"></i>
</div>
do this:
<template v-if="condition">
<div>
<i class="fal fa-caret-left"></i>
</div>
</template>
<template v-else>
<div>
<i class="fas fa-caret-left"></i>
</div>
</template>
Not entirely sure why you need to wrap it twice since I'd think you decouple the i
tag enough by wrapping it once, but it worked for me this way so there's apparently something else going on.
Also, keep in mind that the inner div
can't be replaced with template
for obvious reasons (template tags do not get rendered).
I ran into this issue recently when using Vue.js 2.5.x with FontAwesome 5.5.x — the icon classes were not being updated as expected.
After switching from the FontAwesome Web Fonts + CSS implementation to SVG + JS, the following code no longer worked:
<i :class="[sortByFirstNameAsc ? 'fa-chevron-up' : 'fa-chevron-down', 'fa']"></i>
What would happen is that FontAwesome JavaScript would fire and wrap the <i>
tag and replace it with an SVG element, as in the following simplified example:
<span data-v-2614dbd6="">
<svg data-v-2614dbd6="" class="svg-inline--fa fa-caret-up" ...">
...
</svg>
<!-- <i data-v-2614dbd6="" class="fa fa-caret-up"></i> -->
</span>
Unfortunately, the active class was being toggled on the inner, hidden <i>
tag and not the outer, visible SVG element.
The workaround that restored the dynamic active class toggling was to wrap the FontAwesome icons in a span and use the v-show
directive, as illustrated in the following code snippet:
<span v-show="sortByFirstNameAsc"><i class="fa fa-caret-up"></i></span>
<span v-show="sortByFirstNameDesc"><i class="fa fa-caret-down"></i></span>
The FontAwesome documentation now recommends using their Vue component to avoid conflicts in the DOM:
Compatibility Heads Up! If you are using Vue you need the vue-fontawesome package or Web Fonts with CSS.
The SVG core package is helpful and recommended in the following cases:
"i" tag comments out after fire turning to svg, use some wrap <span v-if="marked"><i class="far fa-check-square"></i></span>
The Font Awesome library you used doesn't know about Vue. It takes the <i>
that you wrote and turns it into an <svg>
, and at that point, it's been stolen from Vue. Vue no longer controls it. The answer that Dialog gave was a good one: wrap it with a <span>
. But then you pointed out another scenario it doesn't work for.
To solve your scenario where wrapping with a <span>
still doesn't work, use key="fa-sort-up"
. This will force Vue to re-render the wrapper, at which point Font Awesome will update the icon. Here's the updated jsFiddle for your example:
<span key="fa-sort-up" v-if="sort && descending"><i class="fas fa-sort-up"></i></span>
<span key="fa-sort-down" v-else-if="sort"><i class="fas fa-sort-down"></i></span>
<span key="fa-sort" v-else><i class="fas fa-sort"></i></span>
You can use anything you want for the key, as long as it's unique.
Toggle a checkbox in vue with FontAwesome
<style>
.fa-check-square::before {
color: green;
}
</style>
<script>
Vue.component('some',
{
data:
function() {
return{
isclick: false
}
},
methods: {
isClicked: function() {
this.isclick = !this.isclick;
}
},
template: '<div id="test" v-on:click="isClicked">' +
'<i v-if="isclick" class="fa fa-check-square" style="font-size: 40px;"></i>' +
'<i v-if="!isclick" class="far fa-square" style="font-size: 40px;"></i>' +
'</div>'
});
</script>
<div id="componentsDemo">
<some></some>
<some></some>
<some></some>
<some></some>
</div>
<script>
new Vue({ el: '#componentsDemo' });
</script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With