Search code examples
javascriptvue.jsvuejs2vue-component

Setting data properties on child components in Vue 2


In Vue I have made a multipage questionnaire using v-show with the make app container being called RiskAssessmentTest.vue.

I have a component to load questionnaire drafts called RiskAssessmentDrafts.vue that looks like this

<template>
    <div>
        <button type="button" class="btn btn-success btn-block rounded" @click="loadDraft(draft)">Continue</button>
    </div>
</template>

<script>
    import Progress from 'easy-circular-progress';
    import moment from 'moment';

    export default {
        components: {
            Progress
        },
        data() {
            return {
                moment: moment
            };
        },
        props: ['drafts'],
        methods: {
            loadDraft(draft) {
                this.$emit('load-draft', draft);
            },
        }
    };
</script>

<style></style>

The loadDraft() method is called in the parent component like this

<template>
<risk-assessment-drafts :drafts="drafts" @load-draft="loadDraftAnswers" />
</template

The loadDraftAnswers() methods grabs the data for the questionnaire and loads it into the child component.

/**
 * Load any draft answers into each question page.
 *
 * @param {*} $draft
 */
async loadDraftAnswers($draft) {
    this.$refs.q1.loadDraftAnswers($draft['test_id'], 0);
    this.$refs.q2.loadDraftAnswers($draft['test_id'], 1);
    this.$refs.q3.loadDraftAnswers($draft['test_id'], 2);
    this.$refs.q4.loadDraftAnswers($draft['test_id'], 3);
    this.$refs.q5.loadDraftAnswers($draft['test_id'], 4);
},

I don't know if its good or bad practice but I then call the loadDraftAnswers() method in the child component.

/**
 * Method called from child that loads into respective draft answers.
 *
 * @param String $testid
 * @param String $question
 *
 * @return void
 */
loadDraftAnswers($testid, $question) {
    axios
        .get(`/risk-assessment-test/get-draft-answers/${$testid}/${$question}`)
        .then((response) => {
    
        })
        .catch((err) => {
            console.log(err);
        });
},

Now to my knowledge this work, as you can see items set on the component in the Chrome dev tools.

enter image description here

However, when I click on the component again in Chrome dev tools, everything is unset.

enter image description here

Is this expected behaviour? How can I make the component retain it's data?

I ask as in the child component I use v-if in places but obviously after initially working everything is null again.

I made a little video too: https://www.awesomescreenshot.com/video/13255023?key=b841eb39bee6c33b3f79ccfc199f8d80


Solution

  • The issue turned out to be that I was using a v-if in a separate area of the same template and for reasons I don't quite understand it was destroying the first and last page components.

    So in essence the data was being loaded into the component and then the component was immediately destroyed so Vue either had nothing to push the data to, or it would add it to what it thought was the first page even though it was actually the second.

    I stumbled across the issue by logging in the lifcycle events created and destroyed

    created() {
        // console.log('Page ' + this.current_page + ' was created in the created hook');
    },
    
    destroyed() {
        // console.log('Page ' + this.current_page + ' was destroyed');
    },
    

    This is probably a rookie error but just in case anyone experiences something similar, this was what helped me.

    (As well as the comments above).