1

I am using Laravel Spark, and have a component within a component.

<parent-component :user="user">

   <child-component :user="user" :questions="questions"></child-component>

<parent-component>

In my parent component I have questions data in my data method:

props: ['user'],
data(){
    return {
        questions: {
            // these are set in another method in this file
        },
    }
},

As you can see, I have added :questions to my child component in the hope of being able to use the questions in that component as I need to loop through them.

In my js file for the child component I have:

props: ['user', 'questions'],

But when trying to use the questions I get a default object unlike the user which contains all the information.

How should this be done correctly as im just guessing currently...

Here is the js file for the child component:

Vue.component('control-question-navigation', {
    props: ['user', 'questions'],
    data() {
        return {
        //
        }
    },
    methods: {
    },
    mounted() {
        var $this = this;
        console.log($this.questions); // return standard object
        console.log($this.user); // returns the user data correctly
    }
});
Karl Hill
  • 12,937
  • 5
  • 58
  • 95
Lovelock
  • 7,689
  • 19
  • 86
  • 186

2 Answers2

1

I think this is an issue with the compilation scope for templates.

You seem to be using something called Content Distribution with Slots, but with incorrect scoping for template variables.

Ref: https://v2.vuejs.org/v2/guide/components.html#Compilation-Scope

Quote from the page:

A simple rule of thumb for component scope is:

Everything in the parent template is compiled in parent scope; everything in the child template is compiled in child scope.

I assume the following lines of template belongs to your root component:

<div id="app">
    <parent-component :user="user">
       <child-component :user="user" :questions="questions"></child-component>
    <parent-component>
</div>

Here, user is already in root component, and therefore it is available to both parent-component and child-component. But your questions is defined in parent-component, and not in root.

As per the compilation scope docs in the link above, you should have questions also in the root component, along with user. Or else you should move your parent component template to its own vue file or into the template string of parent-component definition.

EDIT: Possible solutions for clarity

Option 1: You can define your root component, and include questions also in it along with user:

new Vue({
    el: '#app',
    data: {
        user: "test user",
        questions: ["one", "two", "three"]
    }
});

The above root component will make both user and questions available to both parent-component and child-component.

Option 2: You can avoid using Content Distribution with Slots and instead use a template string:

Vue.component("parent-component", {
    template: `
        <child-component :user="user" :questions="questions"></child-component>
    `,
    props: ["user"],
    data: function() {
        return {
            questions: {} // You can initialize this in a local method here
        }
    }
    // ...
})

Now your child-component will be able to get this.questions belonging to your parent-component

tony19
  • 125,647
  • 18
  • 229
  • 307
Mani
  • 23,635
  • 6
  • 67
  • 54
0
   questions: {
        // these are set in another method in this file
    }

You want to use a computed property.

computed: {
  questions(){ return this.anotherMethodInThisFile() }
},
methods: {
  anotherMethodInThisFile(){ return /* many questions */ }
}

Then alter the method to return the list of questions instead of changing component data and you're done. The template is correct, you just put the logic in the slightly wrong place.

Alex Sakharov
  • 566
  • 3
  • 12