Search code examples
javascriptvue.jsoptimizationvuejs2vue-component

Dynamic content inside the collapse in VueJS 2 (vue) component


I want to make the dynamic content inside the Collapse button/element/dropdown. Because I will reuse it a lot. So how can I pass components inside the Collapse? For example there is some DataTable in the Collapse where I can press "+" button and another collapse would appear(I already made it) and there is another content, and I want to use those collapses, and inside of it wouldn't be a table, but for example a form. I want to Optimize it and use it for future collapses with different content.
I am using VueJS 2, BootstrapVue

Here is my CollapseSection.vue

<template>
  <div class="accordion" role="tablist">
    <b-button block v-b-toggle.accordion-1 class="collapse-btn" align-h="between">
      {{ selectText }}
      <b-icon :icon="visible ? 'caret-down' : 'caret-up'" class="icon"></b-icon>
    </b-button>
    <b-card no-body class="mb-1">
      <b-collapse id="accordion-1" v-model="visible" accordion="my-accordion" role="tabpanel">
        <b-card-body>
          <DataTable :labels="labels" :data="data" :showAdd="true" @add-item="addItem"/>
        </b-card-body>
      </b-collapse>
    </b-card>
//below is dynamic collapse when Click on "+" button
    <div v-for="(item, index) in items" :key="index">
      <b-button block v-b-toggle="'accordion-' + (index + 2)" class="collapse-btn">
        {{ item.name }}
        <b-icon :icon="visible ? 'caret-down' : 'caret-up'" class="icon"></b-icon>
      </b-button>
      <b-card no-body class="mb-1">
        <b-collapse :id="'accordion-' + (index + 2)" accordion="my-accordion" role="tabpanel">
          <b-card-body>
                some content
          </b-card-body>
        </b-collapse>
      </b-card>
    </div>
  </div>
</template>

<script>
export default {
  name: "CollapseButton",
  components: {DataTable},
  props: {
    selectText: {
      type: String,
      default: () => "Select",
    },
  },
  data() {
    return {
      items: [],
      visible: false,
    }
  },
}
</script>
NewForm.vue //is just an example when I call/use it collapse component(only template, cuz script is 
<template>
     <CollapseSection select-text="Collapse ">

     </CollapseSection>
</template>
<script>
export default {
  name: "NewForm",
  components: {CollapseSection},
}
</script>

How to optimize it and make the methods/actions working(because in each collapse would be data and actions/methods that should be interconnected


Solution

  • So, I used the "named slot" and it works great

    Here is my updated CollapseSection.vue

    <b-card no-body class="mb-1">
        <b-collapse id="accordion-1" v-model="visible" accordion="my-accordion" role="tabpanel">
          <div class="d-flex justify-content-end m-2">
            <SearchField class="order-2"></SearchField>
          </div>
          <b-card-body>
            <!--     CONTENT WOULD APPEAR INSIDE THIS SLOT      -->
            <slot name="content" :addItem="addItem"></slot>
          </b-card-body>
        </b-collapse>
    </b-card>
    

    NewForm.vue

    <CollapseSection select-text="Select Images">
          <template #content="{ addItem }">
                 <DataTable :fields="labels" :items="data" :showAdd="true">
                            <b-icon icon="plus" class="add-btn" @click="addItem(data[0].name)">
                    </b-icon>
                 </DataTable>
          </template>
    </CollapseSection>