nicholasnet
nicholasnet

Reputation: 2277

Slot contents are merged between Tabs in VueJS

I have this TabPanel where I am rendering multiple tabs. Each Panel inside TabPanel uses/extends Panel where I am using slots. However, during tab switch content of Tabs are getting merged.

<template>
  <div class>
    <div class>
      <ul class>
        <li
          style="display: inline-block; padding:10px; margin: 10px; border: 1px solid #ccc"
          v-for="(panel, index) in panels"
          :key="index"
          @click="selectTab(index)"
          :ref="'panel' + index"
        >{{ panel.title }}</li>
      </ul>
    </div>
    <div class>
      <slot></slot>
    </div>
  </div>
</template>

<script>
export default {
  name: "TabPanel",
  data() {
    return {
      panels: [],
      selectedIndex: 0
    };
  },
  methods: {
    selectTab(panelIndex) {
      this.selectedIndex = panelIndex;
      this.panels.forEach((panel, index) => {
        panel.isActive = index === panelIndex;
      });
    }
  },
  created() {
    this.panels = this.$children;
  },
  mounted() {
    this.selectTab(0);
  }
};
</script>

Panel code

<template>
  <div v-show="isActive">
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: "Panel",
  props: {
    title: {
      type: String,
      required: true
    },
    panelId: {
      type: String,
      required: true
    }
  },
  data() {
    return {
      isActive: true
    };
  }
};
</script>

Is there anyway to fix this issue. This is the CodeSandbox link to demonstrate this issue since its easier to visualize problem that way I think.

Upvotes: 1

Views: 344

Answers (2)

mrak
mrak

Reputation: 2906

The simplest way to fix the issue is to wrap all components in <Panel>-s:

<TabPanel>
  <Panel title="Dashboard" panel-id="dashboard">
    <Dashboard></Dashboard>
  </Panel>
  <Panel title="Test" panel-id="test">Content from Panel</Panel>
  <Panel title="Rose Panel" panel-id="rose-panel">
    <RosePanel></RosePanel>
  </Panel>
</TabPanel>

https://codesandbox.io/s/eager-brown-6ethk?file=/src/App.vue

But this is probably not what you had in mind.

From what I see, you simply forgot to propagate the "is-active" property to the embedded panel:

  <Panel :title="title" :panelId="panelId" :is-isActive="isActive">Content from Dashboard</Panel>

(e.x in the Dashboard Component)

Upvotes: 0

Hans Felix Ramos
Hans Felix Ramos

Reputation: 4434

Dashboard.vue and RosePanel.vue changes isActive data but they are not doing nothing whit this.

One option is to set a v-show/v-if to each own <Panel>:

<Panel v-show="isActive" :title="title" :panelId="panelId">Content from Dashboard</Panel>

CodeSandbox: https://codesandbox.io/s/charming-hamilton-jz1og

Upvotes: 1

Related Questions