vue3-apexcharts icon indicating copy to clipboard operation
vue3-apexcharts copied to clipboard

Charts are being duplicated

Open Oleksii14 opened this issue 4 years ago • 20 comments

Env:

"apexcharts": "^3.22.2",
"vue": "^3.0.2",
"vue3-apexcharts": "^1.1.1"

My options:

{
 chart: {
        height: 590,
        type: "area",
      },
      dataLabels: {
        enabled: false,
      },
      stroke: {
        curve: "smooth",
      },
      xaxis: {
        labels: {
          showDuplicates: false,
          hideOverlappingLabels: true,
          offsetY: 20,
          style: {
            colors: "#979797",
          },
        },
      },
}

Template:

<apexchart type="area" :height="590" :options="options" :series="series" />

Result:

image

Note: when I change a screen resolution, the duplicated one disappears

Oleksii14 avatar Nov 30 '20 09:11 Oleksii14

Sorry for the late response. Can you please create a Codesandbox demo to reproduce this?

junedchhipa avatar Dec 15 '20 16:12 junedchhipa

Sorry for the late response. Can you please create a Codesandbox demo to reproduce this?

I have fixed this issue by using apexcharts package without vue wrapper. I will attach demo link ASAP

oleksii-shaposhnikov avatar Dec 15 '20 16:12 oleksii-shaposhnikov

Same issue here using the latest versions of Vue, VueApexCharts and ApexCharts I created a Codesandbox here: https://codesandbox.io/s/cool-jennings-qbbr5?file=/src/App.vue

lucasdcrk avatar May 05 '21 18:05 lucasdcrk

Having the same issue. I have to integrate with Vue3 so I can't use ApexCharts native. Any resolution to it?

mijreed avatar May 08 '21 03:05 mijreed

@mijreed you can use it like

<template>
  <div id="chart" />
</template>

<script lang="ts">
import { defineComponent, onMounted } from "vue";
import ApexChart from "apexcharts";

export default defineComponent({
  setup() {
    let chartInstance;

    const options = {
      colors: ["#1890FF", "#FA4F60"],
      chart: {
        type: "area",
      },
      stroke: {
        curve: "smooth",
      },
    };

    const getChartData = () => [
      {
        name: "Test",
        data: [
          {
            x: "1",
            y: 2,
          },

          {
            x: "2",
            y: 2,
          },
        ],
      },
    ];

    onMounted(() => {
      chartInstance = new ApexChart(document.querySelector("#chart"), {
        ...options,
        series: getChartData(),
      });
      chartInstance.render();
    });
  },
});
</script>

Oleksii14 avatar May 08 '21 11:05 Oleksii14

That worked. Thank you!

mijreed avatar May 11 '21 13:05 mijreed

I can confirm, it is a problem with Vue3 using Vite as well. Same issue where if a resize happens the duplicate disappears.

kalenpw avatar Jul 09 '21 00:07 kalenpw

Having this issue too. Opening the development tools or resizing the window causes the duplicate to disappear.

NWBY avatar Jul 21 '21 16:07 NWBY

+1 also having this issue with Vue 3 and Vite

0x62 avatar Aug 06 '21 14:08 0x62

mounted() {
    this.$nextTick(() => {
        window.dispatchEvent(new Event('resize'));
    });
}

Will fix the issue for now

lukesnowden avatar Aug 13 '21 07:08 lukesnowden

Having the same issue.

horia161999 avatar Aug 25 '21 08:08 horia161999

The same here! Hack with event works but doesn't look like a right solution

IvanBalakirev avatar Oct 30 '21 10:10 IvanBalakirev

same issue :/

elreco avatar Nov 08 '21 17:11 elreco

Facing the exactly same issue

haroon97 avatar Nov 24 '21 14:11 haroon97

Me too!

mounted() was too eary for me scenario. I moved the snipped from above to updated().

andreashe avatar Dec 12 '21 18:12 andreashe

Still not fixed

mjwweb avatar Jan 23 '22 20:01 mjwweb

You just need to change mounted() to created(), resolving the issue for me

Flloooow avatar Jan 26 '22 09:01 Flloooow

And if you're using the Composition API (ie <script setup> syntax) use onBeforeMount instead of onMounted.

mperrien avatar Jun 24 '22 15:06 mperrien

And if you're using the Composition API (ie <script setup> syntax) use onBeforeMount instead of onMounted.

its worked well. awesome

gorillaworkout avatar Jul 18 '22 08:07 gorillaworkout

This happens because you mount the component and use reactivity too quickly before the apex component can be initialized. In this case, the init method of the component will be triggered twice, because it is waiting for the next tick to continue. So, instead of arguing with triggering the resize event and having duplicates for a short time, you should wrap your data binding in a call of nextTick. Or add a v-if to your apex component to render it only when all your data has been bound.

This is my work around as long as #50 is not accepted, which adds an additional check within the init method.

razorness avatar Jul 19 '22 13:07 razorness

May I ask why this is closed? I had to implement the nextTick workaround I found via https://stackoverflow.com/a/70826352/2817604 - looks like it was picked from https://github.com/apexcharts/vue3-apexcharts/issues/3#issuecomment-898265002

acidjazz avatar Oct 17 '22 20:10 acidjazz

Which version are you using?

razorness avatar Oct 17 '22 20:10 razorness

"vue3-apexcharts": "^1.4.1",

NuxtJS V3 project using a plugin:

import VueApexCharts from 'vue3-apexcharts'

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(VueApexCharts)
})

acidjazz avatar Oct 17 '22 20:10 acidjazz

just saw your PR and the fix - nice work @razorness - can we get a patch release? i'll update that SO question

acidjazz avatar Oct 17 '22 20:10 acidjazz

this.$nextTick(() => { window.dispatchEvent(new Event('resize')); });

thank you. It works for me

Jonorusc avatar Nov 08 '22 15:11 Jonorusc

[...] I had to implement the nextTick workaround [...]

Until the patch is released, could you share how you implemented this in Nuxt3 @acidjazz ? I'm struggling to do it properly.

jice-lavocat avatar Nov 12 '22 18:11 jice-lavocat

Nuxt V3:

plugins/apex.client.ts

import VueApexCharts from 'vue3-apexcharts'

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(VueApexCharts)
})

components/PublicChartLine.vue

<script lang="ts" setup>
import { ApexOptions } from 'apexcharts'

const options:ApexOptions = {
  colors: ['#6667ab', 'green'],
  tooltip: { theme: 'none' },
  chart: {
    type: 'line',
    toolbar: { show: false },
    foreColor: '#6b7280',
  },
  grid: { show: false },
  markers: {
    size: 6,
    colors: ['#6667ab'],
  },
  xaxis: {
    title: { text: 'Year' },
    tooltip: { enabled: false },
    categories: [2018, 2019, 2020, 2021, 2022],
    axisBorder: { show: false },
    axisTicks: { show: false },
  },
  yaxis: {
    title: { text: 'Days' },
  },
  stroke: {
    show: true,
    curve: 'smooth',
  },
  fill: {
    type: 'gradient',
    gradient: {
      type: 'horizontal',
      colorStops: [
        {
          offset: 1,
          color: '#9c9ae3',
          opacity: 1,
        },
        {
          offset: 100,
          color: '#00c893',
          opacity: 1,
        },
      ],
    },
  },
  dataLabels: {
    style: {
      colors: ['#6667ab'],
    },
  },
}
const series = [
  {
    name: 'Days',
    data: [352, 203, 126, 51, 8],
  },
]

onMounted(() => {
  nextTick(() => {
    window.dispatchEvent(new Event('resize'))
  })
})
</script>

<template>
  <div>
    <apexchart
      class="hidden lg:block w-470px" :options="options" :series="series"
      width="470"
    />
    <apexchart
      class="lg:hidden" :options="options" :series="series"
      width="370"
    />
  </div>
</template>

acidjazz avatar Nov 12 '22 19:11 acidjazz

Thanks, that works like a charm. My code was pretty similar to your, but I tried to do the refresh at the plugin side and not at the component side. Something along the lines:

plugins/apex.client.ts (not working)

import VueApexCharts from 'vue3-apexcharts'

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(VueApexCharts)

  nuxtApp.hook('page:finish', (pageComponent) => {
    nextTick()
    window.dispatchEvent(new Event('resize'))
  })

})

But I couldn't find why this didn't work (I tried several other steps of the lifecycle, like app:mounted without much success).

jice-lavocat avatar Nov 12 '22 22:11 jice-lavocat

I added a ":key" to the graph and it solved.

<apexchart type="area" :options="options" :series="series" :key="chart-items-${series[0].data.length}"></apexchart>

thiagopetherson avatar Feb 22 '23 14:02 thiagopetherson

Window.dispatchEvent(new Event('resize')) on both onMounted and updated caused a visible flick of the duplicate before it got removed. Solved it by reassigning the data.

onMounted(() => {
      nextTick(() => {
        series.value = [...props.graphData];
      })
    })

Josmun55 avatar Apr 04 '23 08:04 Josmun55