Home » vue » VueJS: How do I initialise data so it shows in my template on component load

VueJS: How do I initialise data so it shows in my template on component load

Posted by: admin November 26, 2021 Leave a comment

Questions:

This is driving me nuts!

//ProfilePage.vue
<template>
    <div>
        <p>{{ this.$data.profile.desc }}</p>
        <profileImage v-bind:profile="profile"></profileImage>
        <profileText v-bind:profile="profile" v-on:updateData="updateDesc"></profileText>
    </div>
</template>

<script>
import profileText from './ProfileText.vue';
import profileImage from './ProfileImage.vue';
export default {
    name: 'profilePage',
    component: {
        profileText,
        profileImage
    },
    data() {
        return {
            profile: {
                image: '',
                desc: ''
            }
        }
    },
    created() {
        this.fetchProfile();
    },
    methods: {
        async fetchProfile() {
            const uri = 'http://localhost:8000/api/......get';
            const response = await axios.get(uri);
            .then(response => this.updateProfileData(response.data))
        },
        updateProfileData(data) {
            this.$data.profile.image = data['image'];
            this.$data.profile.desc = data['description'];
        },
        updateDesc(data) {
            this.$data.profile.desc = data.desc;
        },
    }
}
</script>

<style scoped>
</style>

In the above .vue file. I execute a fetch to the back end which successfully returns the correct data from the DB. I successfully save the data returned to the data() part of the file. Next I import a component (the code for which is below) from the correct page, add it as a component and add it to the template and use v-bind to pass in profile from the data() part of this page. Now the imported/child component looks like this:

//ProfileText.vue
<template>
    <div>
        <form @submit="update">
            <textarea v-model="description"></textarea>
            <button type="submit">Submit</button>
        </form>
    <div>
<template>

<script>
export default{
    name: "profileText",
    props: ["profile"],
    data() {
        return {
            description: this.$props.profile.desc
        }
    },
    methods: {
        update(e) {
            e.preventDefault();
            const newData = {
                desc: this.$data.description
            }
            this.$emit('updateData', newData);
        }
    }
}
</script>

<style scoped>
</style>

I use v-model to bind the contents of “description” in data() to the contents of the textarea. I have it so when i edit the text area and click submit the function emits the data to the parent component which triggers a function that updates the parent data() with the new data from the text area of this component. This parts works perfectly.

However, the part I can’t figure out is when the parent component executes the fetch and binds the response with the child component, why isn’t the response showing up in the textarea when it loads.

I have done the exact same thing with another lot of components and it works fine on that lot. The only difference there is that with that lot the execute function brings back a response with an array of data and I use v-for(x in xs) and then bind the attributes of data() with the component x. That’s the only difference. What am I missing in the code above to load the data sent in “profile” from the parent component with v-bind to the textarea in the child component with v-model. In data() i have it to return description: this.$props.profile.desc, but it is not initialising description with profile.desc – Going nuts here [email protected]! I’ve been staring at the code for two days straight trying different things.

Answers:

mounted Function

Called after the instance has been mounted, where el is replaced by
the newly created vm.$el. If the root instance is mounted to an
in-document element, vm.$el will also be in-document when mounted is
called.

Note that mounted does not guarantee that all child components have
also been mounted. If you want to wait until the entire view has been
rendered, you can use vm.$nextTick inside of mounted:

mounted: function () { console.log('component mounted'); }

This hook is not called during server-side rendering.

Source

Component Lifecycle

###

Few things:

  1. Your syntax has errors in the ProfileText.vue file. Missing closing template and div tags
<template>
    <div>
        <form @submit="update">
            <textarea v-model="description"></textarea>
            <button type="submit">Submit</button>
        </form>
    </div>
</template>
  1. You are mixing async/await and .then(). It should be:
async fetchProfile() {
    const uri = 'http://localhost:8000/api/......get';
    const response = await axios.get(uri);

    this.updateProfileData(response.data)
},