Vue FontAwesome icons don't change on compute

Viewed 560

I would like to change header icon based on conversation property.

<a class="navbar-item" :title="$t('header.lock')" @click="makePrivate">
    <i class="fas" :class="getLockClass"></i>
</a>

This is inside computed properties:

isConversationPrivate() {
    return !(Object.keys(this.conversation).length === 0 || this.conversation.user_id === null);
},
getLockClass() {
    console.log(this.isConversationPrivate);
    return this.isConversationPrivate ? 'fa-lock' : 'fa-unlock-alt';
}

So what happens is that when you load the page initially the conversation is empty, so the console log prints out false (non-existing conversation).

Axios request is made to fetch a conversation by ID, it is retrieved (using Vuex) and getLockClass runs again printing true in the console.

Even though the change happened, class never applied. Why doesn't it work?

EDIT:

I have managed to reproduce it on this example:

<html lang="fr">
<body>

<div id="app">
    <a @click="toggle">
        <i class="fas" :class="this.lock ? 'fa-lock':'fa-unlock'"></i>
    </a>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js"></script>
<script>

    new Vue({
        el     : '#app',
        data   : {
            lock: true
        },
        methods: {
            toggle() {
                console.log("here");
                this.lock = !this.lock;
            }
        },
    });
</script>

</body>

</html>
1 Answers

The problem is that your are using a FontAwesome library which will comment out the <i> element and replace it with an <svg>. You can check this if you inspect the element in your browser. FontAwesome recommends that you use vue-fontawesome for that and other reasons: https://fontawesome.com/how-to-use/on-the-web/using-with/vuejs

Another solution would be to wrap the <i> inside another element (like a span):

<span v-show="lock"><i class="fas fa-lock"/></span>
<span v-show="!lock"><i class="fas fa-unlock"/></span>
Related