2

hey my code looks like this:

componentData: [
   { name: TestPane, props: { data: this.cars }, id: 1 },
   { name: TestPane, props: { data: this.persons }, id: 2 },
]
<div v-for="component in componentData" :key="component.id">
   <component v-bind:is="component.name" v-bind="component.props">
   </component>
</div>

the props are not reactive. When I pass the props normally without the loop with :data=cars they are reactive. But I need to pass them in a loop for my project. Any Ideas?

8
  • 1
    you just wrote v-bind that is same like doing :="component.props" it makes no sense. you need to write what you want to pass like v-bind:data Commented Nov 13, 2020 at 14:06
  • 1
    Assuming componentData is defined in the same data block as cars and persons, that's the problem. They won't exist at the time you define componentData, even if they are listed above. (The v-bind syntax is valid though.) Commented Nov 13, 2020 at 14:09
  • Can you add to your TestPane this: created(){console.log(this.data);} ? Commented Nov 13, 2020 at 14:18
  • If @Dan is right, you can check this answer stackoverflow.com/questions/49614837/… Commented Nov 13, 2020 at 14:20
  • Ifaruki v-bind is valid, like the documentation Dan linked says. @Dan yes you are right. Is there a solution for my problem? Commented Nov 13, 2020 at 14:21

1 Answer 1

1

It would work unless you've defined your data like this:

data() {
  return {
    cars: [ ... ],
    persons: [ ... ],
    componentData: [
      { name: TestPane, props: { data: this.cars }, id: 1 },
      { name: TestPane, props: { data: this.persons }, id: 2 },
    ]
  }
}

this.cars and this.persons aren't accessible when you define componentData. Use a computed to maintain reactivity:

new Vue({
  el: "#app",
  data() {
    return {
      cars: [ ... ],
      persons: [ ... ]
    }
  },
  computed: {
    componentData() {
      return [
        { name: TestPane, props: { data: this.cars }, id: 1 },
        { name: TestPane, props: { data: this.persons }, id: 2 },
      ]
    }
  }
});

EDIT: Here's a demo

const TestPane = {
  template: `
    <div class="pane">
      {{ data }}
    </div>
  `,
  props: ['data']
}

/***** APP *****/
new Vue({
  el: "#app",
  data() {
    return {
      cars: ['honda', 'ferrari'],
      persons: ['Bob', 'Mary']
    }
  },
  computed: {
    componentData() {
        return [
        { name: TestPane, props: { data: this.cars }, id: 1 },
        { name: TestPane, props: { data: this.persons }, id: 2 },
      ]
    }
  }
});
.pane {
  padding: 12px;
  background: #dddddd;
  margin: 4px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div v-for="component in componentData" :key="component.id">
     <component v-bind:is="component.name" v-bind="component.props">
     </component>
  </div>
</div>

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

4 Comments

Hey I tried all your solutions while you was editing :D Your solution is working, except in the initial load. I get multiple undefined messages there, but after that it works fine. How can I initiate the computed data with null, so that I can do a v-if?
Ha, changed my mind after the first version wasn't reactive. If you're loading the data async, you could either wrap the v-for with a v-if until it arrives (preferable), or you could do something like data: this.cars || [] and data: this.persons || [] in the computed.
i load the data via api calls in the mounted hook. So yeah I want to use v-if on the whole component array. But how? In your 'before-editing' solution I could used "v-if="componentData" because it was null initially.
That's usually done with a v-if="isLoaded" data property you create, which starts as false and you set to true when the async operation completes

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.