score:1

Accepted answer

as i wrote in my comment, the charts are rendered twice. this causes flickering.

// every time you use <chart-display>, 2 charts are rendered, this means chart 1 renders
// itself and chart 2, char 2 renders itself and chart 1, this is a bad pattern in vue in general

mounted() {
  this.check(8, "chart_8");
  this.check(7, "chart_7");
}

make the following changes:

chartdisplay.vue

<template>
  <div
    class="chart-container"
    style="position: relative; height: 40vh; width: 100%"
  >
    <canvas ref="chart_7"></canvas>
    <canvas ref="chart_8"></canvas>
  </div>
</template>

<script>
import chart from "chart.js";
export default {
  name: "chartdisplay",
  data() {
    return {
      date: [],
      challenge: [],
      data: [],
      // save charts in an array
      charts: [],
      // charts options
      options: {
        linetension: 0,
        maintainaspectratio: false,
        scales: {
          yaxes: [
            {
              scalelabel: {
                display: false,
              },
              ticks: {
                beginatzero: true,
                callback(value) {
                  return `${value}%`;
                },
              },
            },
          ],
          xaxes: [
            {
              type: "time",
              time: {
                unit: "month",
              },
              scalelabel: {
                display: true,
              },
            },
          ],
        },
      },
    };
  },
  mounted() {
    this.render(7, this.$refs.chart_7);
    this.render(8, this.$refs.chart_8);
  },
  methods: {
    render(id, ctx) {
      this.fetchdata(id).then((response) => {
        let data = response.date.map((date, index) => ({
          x: new date(date * 1000),
          y: response.challenge[index],
        }));
        this.charts.push(
          new chart(ctx, {
            type: "line",
            data: {
              datasets: [
                {
                  label: "challenge",
                  data: data,
                  bordercolor: " #ea5455",
                },
              ],
            },
            options: this.options,
          })
        );
      });
    },
    fetchdata(id) {
      return this.$http.get(`/api_chart/${ id  }/full`);
    },
  },
  beforedestroy() {
    this.charts.foreach((chart) => chart.destroy());
  },
};
</script>
<style >
[v-cloak] {
  display: none;
}
</style>

app.vue

<template>
  <div>
    <div class="in order to display chart1">
      <chart-display/>
    </div>
  </div>
</template>

<script>
import chartdisplay from "./chartdisplay.vue";
export default {
  components: { chartdisplay },
};
</script>

see it on sandbox

score:1

i found several errors on your code. i fix them in sandbox

for chat.vue :

  • i rename the file as chartdisplay.vue as similar as the component name
  • import chart.js package for using chart() function
  • i use a demo api
<template>
      <div
        class="chart-container"
        style="position: relative; height: 40vh; width: 100%"
      >
        <slot name="test1"></slot>
        <slot name="test2"></slot>
      </div>
    </template>

<script>
  import chart from "chart.js";
  export default {
    name: "chartdisplay",
    data() {
      return {
        date: [],
        challenge: [],
        data: [],
      };
    },
    mounted() {
      this.check(8, "chart_8");
      this.check(7, "chart_7");
    },
    methods: {
      check(id, name) {
        fetch(
            "https://api.wirespec.dev/wirespec/stackoverflow/fetchchartdataforvuejs"
          )
          .then((response) => response.json())
          .then((response) => {
            this.date = response.date;
            this.challenge = response.challenge;
            this.data = this.date.map((date, index) => ({
              x: new date(date * 1000),
              y: this.challenge[index],
            }));
            const ctx = document.getelementbyid([name]).getcontext("2d");
            new chart(ctx, {
              type: "line",
              data: {
                datasets: [{
                  label: "challenge",
                  data: this.data,
                  bordercolor: " #ea5455",
                }, ],
              },
              options: {
                linetension: 0,
                maintainaspectratio: false,
                scales: {
                  yaxes: [{
                    scalelabel: {
                      display: false,
                    },
                    ticks: {
                      beginatzero: true,
                      callback(value) {
                        return `${value}%`;
                      },
                    },
                  }, ],
                  xaxes: [{
                    type: "time",
                    time: {
                      unit: "month",
                    },
                    scalelabel: {
                      display: true,
                    },
                  }, ],
                },
              },
            });
          });
      },
    },
  };
</script>

for app.vue

  • your import should not carry any hyphen.
  • component should be components
  • render the component once to avoid flikering
<template>
  <div>
    <div class="in order to display chart1">
      <chart-display>
        <canvas slot="test1" id="chart_7"></canvas>
        <canvas slot="test2" id="chart_8"></canvas>
      </chart-display>
    </div>
  </div>
</template>

<script>
  import chartdisplay from "./chartdisplay.vue";
  export default {
    components: {
      chartdisplay
    },
  };
</script>

Related Query

More Query from same tag