Search code examples
javascriptvue.jsvuejs2v-for

Inside of one v-for, How to use another v-for in Vuejs?


BaseAccordion.vue

<template>
  <div class="wrapper">
    <div class="accordion">
      <input type="checkbox" @click="toggleItem" />
      <h2 class="title">
        <slot name="title"></slot>
      </h2>
    </div>
    <div v-show="show" class="content">
      <slot name="content"></slot>
    </div>
  </div>
</template>
<script>
export default {
  components: {},
  data: function () {
    return {
      show: false,
    };
  },
  methods: {
    toggleItem: function () {
      this.show = !this.show;
    },
  },
};
</script>
<style scoped>
.wrapper {
  margin: 0 auto;
  width: 300px;
  padding: 10px;
}
.accordion {
  display: flex;
  cursor: pointer;

  margin: 0;
}
.title {
  margin: 0;
  color: darkgreen;
}
.content {
  text-align: left;
  width: 100%;
  border-bottom: 1px solid black;
  padding: 10px;
}
</style>

Issue with the above code is that,

When trying to iterate the list inside of another list(I mean like, inside of one v-for, using another v-for)

I am getting each value repeatedly for 6 times, and the sub items also coming repeatedly. because of repeatedly items display.


Solution

  • For the requirement to achieve, you should run the second for loop only inside v-slot:content

    HelloWorld.vue

    Template

    <div v-for="box in boxes" :key="box.id">
      <BaseAccordian>
        <template v-slot:title>{{ box.name }}</template>
        <template v-slot:content>
          <div
            v-for="paint in paints"
            :key="paint.id"
            class="line"
            :class="{
              green: paint.status === 'ok',
              red: paint.status === 'notok',
              pink: paint.status === 'medium',
            }"
          >
            <div>{{ paint.name }}</div>
          </div>
        </template>
      </BaseAccordian>
    </div>
    

    CSS

    .content > .line > div {
      --line-width: 2px;
      --x-offset: 8px;
      --x-width: 120px;
    
      position: relative;
      padding-bottom: var(--line-width);
    }
    .content > .line > div:before {
      content: "";
      display: block;
      position: absolute;
      bottom: 0;
      left: var(--x-offset);
      width: var(--x-width);
      height: 100%;
      border-left: var(--line-width) dashed currentColor;
      border-bottom: var(--line-width) dashed currentColor;
    }
    .content > .line > div:after {
      content: "";
      display: block;
      position: absolute;
      bottom: calc(-1 * var(--line-width) * 1.75);
      left: calc(var(--x-offset) + var(--x-width));
      width: 0;
      height: 0;
      border: calc(var(--line-width) * 2.5) solid transparent;
      border-right: 0;
      border-left: calc(var(--line-width) * 5) solid currentColor;
    }
    

    Working Code

    Fiddle