1

I have the following

<tabs>
    //If tab.name is not null
    <tab v-for="tab in tabs" :key="tab.id" :name="tab.name" :suffix="tab.id">
    </tab>
    //If tab.name is null
    <tab v-for="tab in tabs" :key="tab.id" :name="tab.id">
    </tab>
</tabs>

I want to run a loop for my data and render the component differently based on my condition.

I can't for the life of me figure out how to do that. v-else requires another element declaration, but if you put v-for in both it will just run the loop twice. I tried this but it doesnt seem to work in my case. If I do <template :name="tab.name"> the component says it's missing the required property name.

How is this supposed to work in vue?

martixy
  • 784
  • 1
  • 10
  • 26

2 Answers2

4

You can use v-for on a <template> element and use v-if inside:

<tabs>
    <template v-for="tab in tabs">
        <!-- //If tab.name is not null -->
        <tab v-if="tab.name" :key="tab.id" :name="tab.name" :suffix="tab.id">
        </tab>
        <!-- //If tab.name is null -->
        <tab v-else          :key="tab.id" :name="tab.id">
        </tab>
    </template>
</tabs>

Demo:

Vue.component('tab', {
  props: ['name', 'suffix'],
  template: `<div>tab - name: {{ name }} - suffix: {{ suffix || 'not available' }}</div>`
});
Vue.component('tabs', {
  props: ['tabs'],
  template: `<div>tabs<hr><slot :tabs="tabs"></slot></div>`
});
new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!',
    tabs: [{id: 1, name: "Alice"}, {id: 2}]
  }
})
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <tabs :tabs="tabs">
    <template v-for="tab in tabs">
      <!-- //If tab.name is not null -->
      <tab v-if="tab.name" :key="tab.id" :name="tab.name" :suffix="tab.id"></tab>
      <!-- //If tab.name is null -->
      <tab v-else          :key="tab.id" :name="tab.id"></tab>
    </template>
  </tabs>
</div>
tony19
  • 125,647
  • 18
  • 229
  • 307
acdcjunior
  • 132,397
  • 37
  • 331
  • 304
  • I had actually just started writing my own answer with the exact same technique(interestingly, the opposite of the answer I linked to in my original question). While @DobleL provided an amusing hack, this is indeed the correct answer, though I guess it came a few minutes too late. – martixy Mar 25 '18 at 19:38
  • `template` is the first line of defense; just be aware it doesn't work in IE, in which case you have to revert to a render function. – Bert Mar 25 '18 at 19:41
  • I have a further question: How do I avoid duplication of the of the tab and everything **inside**? If there is a lot of additional code inside, anytime I change anything I have to remember to change it in both places. This seems a terrible outcome just because one property on some ancestor somewhere may not exist. There has to be a way out... – martixy Mar 25 '18 at 22:30
  • Hum.. this seems an interesting problem. Though I think with a concrete case we could help you better. Can you write a sample/ask in a new question? (This is good because more people can help as well) – acdcjunior Mar 25 '18 at 22:32
0

you can try this

<tabs>
    //If tab.name is not null
   <tab v-for="tab in tabs" :key="tab.id" :name="tab.name" :suffix="tab.id">
        <template v-if="tab.name != null">
           // conditional if code
        </template>
        <template v-else>
           // conditional else code
        </template>
   </tab>
</tabs>
  • If you read the question to the end you will see I have already tried something similar, and it hasn't worked. I say "similar", because let me ask you this: Right now you unconditionally put the `tab.name` in `:name`. But sometimes `tab.id` has to go in there instead. How? – martixy Mar 25 '18 at 18:31