How to get data from a nested component



  • I have this 3 components. One is for the Question component that consists of questions. The second is for QuestionOption for the list of choices. And the third one is my main component. How do I get the data from the QuestionOption component to the main component. Since the main component is not the parent of the QuestionOption I cannot use the $emit. Also I make use of bus but it’s not working on my case. Can anyone help me on this.

    Also how will I get all the chosen answers after the submission of the button? Here is my code.

    Main.vue

        <div class="quiz-background">
    
            <question 
                v-for="(question, $indexParent) in randomQuestions"
                :question="question['doc'].question"
                :choices="question['doc']['choices']"
                :indexParent="$indexParent"
                :correctAnswer="question['doc'].correctAnswer"
            >               
            </question>
    
            <section style="margin:16px">
                <v-ons-button
                    modifier="cta" 
                    @click="submit" 
                    v-show="!isDone"
                >Submit
                </v-ons-button>
            </section>
    
        </div>
    

    Question.vue

    <template>
    
    <v-ons-list>
        <v-ons-list-header>
            {{indexParent + 1}}.{{ question }}
        </v-ons-list-header>
        
        
        <question-option 
            v-for="(choice, key, $index) in choices" 
            :choice="choice" 
            :letter="key" 
            :indexParent="indexParent" 
            :index="$index"
            :correctAnswer="correctAnswer"
        >
            
        </question-option>
            
    
    </v-ons-list>
    
    
    </template>
    
    <script>
    import QuestionOption from './QuestionOption.vue';
    
    export default {
    
    
        props: ['question', 'indexParent', 'choices', 'correctAnswer'],
    
        components: {
            QuestionOption
        }
    }
    </script>
    

    QuestionOption.vue

    <template>
    <v-ons-list modifier="inset">
        <v-ons-list-item
            :name="'question-' + indexParent"
            
            :modifier="longdivider"
            :key="letter"
            tappable
        >
            <label class="left">
                <v-ons-radio    
                    :name="'question-' + indexParent"
                    :input-id="indexParent + '-' + index"
                    :value="letter"
                    :key="letter"
                    v-model="chosenAnswer"
    
                >   
                </v-ons-radio>
            </label>
    
            <label 
                class="center" 
                :for="indexParent + '-' + index"    
                :class="{'success' : isSuccess, 'danger' : isDanger}"       
            >
                {{ letter }} . {{ choice }}
            </label>
    
        </v-ons-list-item>
        
        
    </v-ons-list>
    
    </template>
    
    <script>
    
    import Vue from 'vue';
    
    var bus = new Vue();
    
    export default {
    
    
        data() {
    
            return {
                chosenAnswer: ''
            }
        },
    
        props: ['letter', 'choice','correctAnswer', 'indexParent', 'index'],
    
        computed: {
            isSuccess () {
                return this.chosenAnswer === this.correctAnswer;
            },
            isDanger () {
    
                return this.chosenAnswer !== this.correctAnswer;
            }
        },
    
    
    }
    </script>

  • Onsen UI

    @jayGorio

    Short answer: Vuex

    Long answer:

    • Use this.$emit('customEvent', ...) in QuestionOption and @customEvent="$emit('customEvent', $event) in Question to forward it to the parent.
    • Pass a function from the main component all the way down to QuestionOption via props and let that function modify the main component’s state. That way you can modify something in the main component from the last child component.
    • this.$root is always present in non functional components, so you can use it as a bus as well: this.$root.$on(...) and this.$root.$emit(...).


  • @Fran-Diox thanks for your answer.