0

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 $@! I've been staring at the code for two days straight trying different things.

2 Answers 2

2

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

Sign up to request clarification or add additional context in comments.

1 Comment

thank you Fouèd Moussi for getting me thinking about which component's mounted gets called first. Turns out my child component's mounted gets called before the parent component's mounted. called axios.get in child component, problem solved.
0

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)
},

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.