[Vuejs]-How to append component as a child dynamically

2๐Ÿ‘

โœ…

Try not to do direct DOM manipulation if you can. There is almost always a better way with Vue. In your case, a simple array can hold true/false values for conditionally displaying a chart underneath your add/remove buttons. The buttons toggle the appropriate array value, and the chart only displays if that value is true using v-if

<template>
  <div class="monitor-container">
    <div class="monitor_interface-chart-container" v-for="index in 6" :key="index">
      <i @click="addChart(index)" class="pi pi-plus-circle new_chart-icon">click me</i>
      <i @click="removeChart(index)" class="pi pi-minus-circle">remove me</i>
      <BaseChart v-if="chartArray[index]" />
    </div>
  </div>
</template>
<script>
import 'primeicons/primeicons.css';
import BaseChart from '@/components/charts/BaseChart.vue'
export default {
  components: {
    BaseChart,
  },
  data() {
    return {
      chartArray: [],
    };
  },
  methods: {
    addChart(index) {
      this.$set(this.chartArray, index, true);
    },
    removeChart(index) {
      this.$set(this.chartArray, index, false);
    },
  },
};
</script>

The this.$set() syntax comes from Vue 2โ€™s method for updating array values by index while maintaining reactivity

๐Ÿ‘คyoduh

1๐Ÿ‘

in my opinion, one of the best solutions is to create an array with graphs, the elements of which will contain a flag that allows you to adjust the display of each graph.
The final version will look approximately like this.

<template>
  <div class="monitor-container">
    <div
      class="monitor_interface-chart-container"
      v-for="chart in charts"
      :key="chart.id"
    >
      <BaseChart v-if="chart.isShown" />
      <i
        v-if="!chart.isShown"
        @click="addChart(chart.id)"
        class="pi pi-plus-circle new_chart-icon"
        >+</i
      >
      <i
        v-else
        @click="removeChart(chart.id)"
        class="pi pi-plus-circle new_chart-icon"
        >-</i
      >
    </div>
  </div>
</template>

<script>
import BaseChart from "@/components/charts/BaseChart.vue";
export default {
  components: {
    BaseChart,
  },
  data() {
    return {
      charts: [
        {
          id: 1,
          isShown: true,
        },
        {
          id: 2,
          isShown: true,
        },
        {
          id: 3,
          isShown: true,
        },
        {
          id: 4,
          isShown: true,
        },
        {
          id: 5,
          isShown: true,
        },
        {
          id: 6,
          isShown: true,
        },
      ],
    };
  },
  methods: {
    addChart(id) {
      const chart = this.charts.find((chart) => chart.id === id);
      if (chart) {
        chart.isShown = true;
      }
    },
    removeChart(id) {
      const chart = this.charts.find((chart) => chart.id === id);
      if (chart) {
        chart.isShown = false;
      }
    },
  },
};
</script>

This solution is applicable for a fixed array length. If you plan to create an unlimited number of graphs, then the code will have to be changed.
In this case, we cannot use the index as a key when iterating through v-for. When adding a new element, you need to generate a unique id and add a new element to the array. To delete an element, you just need to filter the current array by the element id.

<template>
  <div class="monitor-container">
    <div
      class="monitor_interface-chart-container"
      v-for="chart in charts"
      :key="chart.id"
    >
      <BaseChart />
      <i @click="removeChart(chart.id)" class="pi pi-plus-circle new_chart-icon"
        >-</i
      >
    </div>
    <i @click="addChart()" class="pi pi-plus-circle new_chart-icon">+</i>
  </div>
</template>

<script>
import BaseChart from "@/components/charts/BaseChart.vue";

export default {
  components: {
    BaseChart,
  },
  data() {
    return {
      charts: [],
    };
  },
  methods: {
    addChart(id) {
      const biggestId = this.charts.reduce(
        (acc, rec) => (acc.id > rec.id ? acc.id : rec.id),
        0
      );
      this.charts.push({ id: biggestId + 1 });
    },
    removeChart(id) {
      this.charts = this.charts.filter((chart) => chart.id !== id);
    },
  },
};
</script>

Leave a comment