Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue.js directive v-html not updating if the model is overwritten

By running the following code (a Vue.js component), I expect that, after the AJAX call returns, both the v-html directive and the console.log() display the same value.

On the contrary, v-html is stuck with "loading...(1)" even though obj.html has a different value, as console.log() confirms.

The behaviour is caused by getObject overwriting obj, and being afterwards obj.html undefined for a short time before getHTML returns (all this happens in function created).

Can please someone explain whether this is Vue's desired behavior (doc links are welcome), or whether should I submit a bug report, or finally whether I am simply structuring my code in a bad way?

Thanks in advance

<template>
    <main v-html="obj.html || 'loading... (1)'">
    </main>
</template>

<script>
export default {
    name: 'Post',

    data: function () {
        return {
            obj: {
                html: 'loading... (2)'
            }
        }
    },

    created: async function () {
        this.obj = await this.getObject()
        this.obj.html = await this.getHtml()
        console.log(this.obj.html)
    },

    methods: {
        getObject: async function () {
            const resp = await this.$http.get('https://jsonplaceholder.typicode.com/todos')
            return resp.body[0]
        },
        getHtml: async function () {
            const resp = await this.$http.get('https://jsonplaceholder.typicode.com/todos')
            return resp.body[0].title
        },
    }
}
</script>
like image 856
leonixyz Avatar asked Nov 07 '22 01:11

leonixyz


1 Answers

The function getObject returns a String so at the first line of created hook

this.obj = await this.getObject()

you change the reference of the obj and you make it pointing to a string and then you try to put a property on a string, which does not work ;)

it's like you would do
this.obj = 'test'
then
console.log(this.obj);
// test

and then
this.obj.abc = 'whatever'
console.log(this.obj.abc);
// undefined

You would need to parse the object before, see JSON.parse(string)

Update: If this is not the case i.e you somehow have an object coming from that service. Then the only problem I can think is that you lose the reference of your original obj and v-html is still pointing to the old one. In that case you have to avoid modification of the root obj or you can use the vue $set method: https://v2.vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats

like image 164
V. Sambor Avatar answered Nov 14 '22 23:11

V. Sambor