apexcharts / vue-apexcharts

📊 Vue 2 component for ApexCharts
https://apexcharts.com
MIT License
1.33k stars 135 forks source link

Apexcharts data is not shown initially and after refresh #185

Open vhniii opened 4 years ago

vhniii commented 4 years ago

I have vue application where data is passed to apexchart from vuex. The problem is with displaying data on chart while initially going to a page which uses the component where apexchart is used. If I go back to home page and then back to the page where the chart is then data is showing. but after refresh data is again not showing. ` My component:

<template> 
     <div>
        <div class="item-chart">
            <apexcharts type="area" class="apexChart" width="100%" height="400px" :options="chartOptions" :categories="categories" :series="series"></apexcharts>
        </div>

        <div class="btn-back">
            <router-link to="/">Back</router-link>
        </div>
    </div>
</template>

<script>
import VueApexCharts from "vue-apexcharts";

export default {
    name: 'currency',
    components: {
        apexcharts: VueApexCharts
    },
    data() {
        return {
            chartOptions: {
                chart: {
                    id: 'chart',
                    toolbar: {
                        show: false
                    }
                },
                xaxis: {
                    categories: [],
                    labels: {
                        style: {
                            colors: '#F1C40F'
                        }
                    }
                },
                yaxis: {
                    show: false
                },
                dataLabels: {
                    enabled: false
                },
                colors: ['#F1C40F']
            },
            series: [{
                name: 'Price',
                data: this.$store.state.currencyHistory.BTC.map(i => i.close),
            }]
        }      
    },
    created() {
        this.getCryptoCurrencyData()
        this.getCurrencyHistory()
        this.chartOptions.xaxis.categories = this.Times
    },
    methods: {
        getCryptoCurrencyData() {
            this.$store.dispatch('getCryptoData')
        },
        getCurrencyHistory() {
            this.$store.dispatch('getCurrencyHistory')
        },
        getChartPrices() {
            this.currencyHistory.BTC.map(i => i.close)
        },
        getChartTimes() {

            const data = [];
            this.$store.state.currencyHistory.BTC.map(i => {
                let time = new Date(i.time * 1000);
                data.push(time.toLocaleString('en-US', { hour: 'numeric', hour12: true}))
            })

            return data;
        }
    },
    computed: {
        cryptoCurrencyData() {
            return this.$store.getters.showCryptoData
        },
        currencyHistory() {
            return this.$store.getters.showCurrencyHistory
        },
        Times() {
            return this.getChartTimes()
        }
    }
}
</script>

Also why I canno't give data from vuex store to apexchart with getters, its just not working. (I have to use "this.$store.state").

I would like to know how to fix the problem where data will be showed every time (even if I go to the page first time after running the app) and also showed after refresh.

Thank you in advance

woutvw commented 4 years ago

I have the same problem, the chart only shows when I resize the browser. Have you found a sollution already?

theDevelopper commented 4 years ago

Any updates on this one. I have the same issue with line charts. My line charts are not drawing until I resize the browser. Other chart types like bar and pie work fine.

firedev commented 4 years ago

I got it to work by triggering window.resize manually after updating series:

window.dispatchEvent(new Event('resize'))
wirakw2 commented 4 years ago

@firedev how you trigger it ?

KayJay89 commented 4 years ago

@firedev how you trigger it ?

For use with Vuex (not sure this is what you need though), you can use @firedev's solution by including

window.dispatchEvent(new Event('resize'))

in your mutation like so:

NAME_OF_MUTATION: (state, dataToAdd) => {
      state.nameOfDataInStore = dataToAdd;
      window.dispatchEvent(new Event("resize"));
    },

I'm doubtful this a good practice but this is the only way I could get the charts to update using Vuex.

As to @vhniii's point of not being able to pass store data using getters, that does work on my end perfectly fine.

EDIT:

Actually guys, seems like it works after all and I was doing something wrong (not surprising).

Found the answer in the documentation: image

When applying the above for update of chart options, the data loads properly without the need for a hacky manual window event.

FelixWaigner commented 3 years ago

Any solutions on this problem yet?

theolevisage commented 3 years ago

@KayJay89 Which doc are you referring to please ? I can't find that bit in the apex chart doc in the Vue.js section or even in the updateChart part...

I'm still having this issue and I have to resize to get the data, I'm using the Vuex and I don't see where I'm doing wrong (although there is probably a lot I'm doing wrong haha)

My chart options and series are fully in the vuex and I'm just inserting them into my apexchart component with mapGetters but my chart is empty on load and doesn't update the data after I mutated the state.

If anybody has a solution that would be great.

ridwankustanto commented 3 years ago
window.dispatchEvent(new Event('resize'))

Thanks! It works for me

Herant commented 3 years ago

Is there really no other way to make charts reactive than to call resize event?

gdagrech commented 3 years ago

The only way I could solve the problem of rendering an empty board even when the child receives the info was by adding an ngIf directive. image

That way it doesnt matter how many time you refresh the page it will always render the chart correctly

image

otherperspectives commented 3 years ago

window.dispatchEvent(new Event('resize'))

This workes like a charm. Thanks!!!

DennisMwongera commented 3 years ago

My Donut chart renders for a sec then disappears, when I switch the view tab to a bar chart once then I return to the donut chart it renders well this time round My data comes from the store

drewm1192 commented 3 years ago

@DennisMwongera This is exactly what is happening to me with a radial bar chart and I cannot figure out why. I would have assumed the issue is with getting the data when componentDidMount() runs, but the other visuals populate with the same dataset, so it has to be an Apex issue... (I'm using React).

5Sense-PhuocLoiTran commented 3 years ago

Any solutions on this problem when refresh yet?

DennisMwongera commented 3 years ago

When Using React, try giving your series Array some data to work with like series: [ 1, 1, 1, 1, 1 ] this will communicate to the chart there is some data to work with until the store loads up the data and updates your series(React) @drewm1192 @5Sense-PhuocLoiTran

DennisMwongera commented 3 years ago

For me am using Vue still trying to figure out a way through

raysubham commented 2 years ago

When Using React, try giving your series Array some data to work with like series: [ 1, 1, 1, 1, 1 ] this will communicate to the chart there is some data to work with until the store loads up the data and updates your series(React) @drewm1192 @5Sense-PhuocLoiTran

This worked for me perfectly! Thank you so much! I had to add data in the series instead of a empty array and also add Resize Event Dispatcher line mentioned earlier in the thread.

cflurin commented 2 years ago

I had a similar issue with the latest apexcharts version 3.30.0, downgrating to v3.22.2 solved the issue for me.

MinSomai commented 2 years ago

I have been using keys in each chart component to force render. It was working fine.

As alternative, this also works. downgrade apexcharts and vue-apexcharts to these specific versions. I tried downgrading only one of them and the problem persists.

"apexcharts": "3.24.0", "vue-apexcharts": "1.5.3",

cflurin commented 2 years ago

Here my latest working versions:

apexcharts v3.29.0 vue-apexcharts v1.6.2

cflurin commented 2 years ago

I have been using keys in each chart component to force render. It was working fine.

Hi, how did you use keys, can you post an example.

MinSomai commented 2 years ago

Hi, how did you use keys, can you post an example.

set key `

`

data testKey = 1;

update options/series then change testKey like so, and it will force render the component testKey++;

cflurin commented 2 years ago

Thanks, I tried a similar approach (new_data) but it didn't work with apexcharts v3.30.0

MinSomai commented 2 years ago

Thanks, I tried a similar approach (new_data) but it didn't work with apexcharts v3.30.0

you have to manually trigger key change testKey++ after you load options and series.

you can try refresh too. like this

`

`

manually, somewhere in your method this.$refs.myChart.refresh()

cflurin commented 2 years ago

Okay, I'll try. Anyway with v3.29.0 it works for me without any additional code.

sobancodes commented 2 years ago

I just had a similar issue that the chart was only showing data when I resized the browser. Here is how I solved it for my use case through experimentation and some help from the documentation. First, add a ref on apexcharts component.

<apexcharts type="area" ref="apexChart" class="apexChart" width="100%" height="400px" :options="chartOptions" :categories="categories" :series="series" />

then call updateSeries or updateOptions or both depending upon the use case.

this.$refs.apexChart.updateSeries(this.response.series); this.$refs.apexChart.updateOptions({ xaxis: { categories: this.response.labels, } })

on the page visit or whenever the data is not loading basically. I had to do it in watcher since in my case the data was not updating after an API call. But, I have not tested this with the router.

Version: 3.31.0

rognales commented 2 years ago

This is still happening. I have to pinned to 3.29 as shared to resolved this.

greenyboiz commented 2 years ago

`

</div>
<div style="margin-left: -14px" v-else>
  <VueApexCharts height="240" :options="chartOptions" :series="ratioEmpty" />
</div>`

at else case, it still doesnt render anything iniatially but when resize the window, it goes, (my "ratioEmpty" contains object {x: '70', y: 0} ). Please help me out this case :((

MinSomai commented 2 years ago

<div style="margin-left: -14px" v-if="!isEmpty"> <VueApexCharts height="240" :options="chartOptions" :series="series" /> </div> <div style="margin-left: -14px" v-else> <VueApexCharts height="240" :options="chartOptions" :series="ratioEmpty" /> </div> at else case, it still doesnt render anything iniatially but when resize the window, it goes, (my "ratioEmpty" contains object {x: '70', y: 0} ). Please help me out this case :((

from your comment this is what I think is the issue. series (ratioEmpty in your case) takes an array and not an object.

examples:

series: [{
          name: 'series-1',
          data: [30, 40, 35, 50, 49, 60, 70, 91]
        }]

or

series:[{
  data: [23, 34, 12, 54, 32, ... , 43]
}]

or for pie charts

series: [23, 11, 54, 72, 12],
greenyboiz commented 2 years ago

<div style="margin-left: -14px" v-if="!isEmpty"> <VueApexCharts height="240" :options="chartOptions" :series="series" /> </div> <div style="margin-left: -14px" v-else> <VueApexCharts height="240" :options="chartOptions" :series="ratioEmpty" /> </div> at else case, it still doesnt render anything iniatially but when resize the window, it goes, (my "ratioEmpty" contains object {x: '70', y: 0} ). Please help me out this case :((

from your comment this is what I think is the issue. series (ratioEmpty in your case) takes an array and not an object.

examples:

series: [{
          name: 'series-1',
          data: [30, 40, 35, 50, 49, 60, 70, 91]
        }]

or

series:[{
  data: [23, 34, 12, 54, 32, ... , 43]
}]

or for pie charts

series: [23, 11, 54, 72, 12],

thanks for your reply, actually, my ratioEmpty is an array containing some of that object like that to handle the null value of the y-axis. Update: I found the issue, that's all my stupid fault. Thank you

rodpatulski commented 2 years ago

This is also an issue with reactapexcharts

pradeepbp1310 commented 2 years ago

I was also facing the same issue, fixed it by using a toggle variable in which the initial value isChartLoading = false and making it true after updating the series.

<ng-container *ngIf="isChartLoading">
      <apx-chart
        [series]="chartOptions.series"
        [chart]="chartOptions.chart"
        [colors]="chartOptions.colors"
        [labels]="chartOptions.labels"
        [legend]="chartOptions.legend"
        [dataLabels]="chartOptions.dataLabels"
        [plotOptions]="chartOptions.plotOptions"
        [stroke]="chartOptions.stroke"
        [responsive]="chartOptions.responsive"
        [tooltip]="chartOptions.tooltip"
      >
      </apx-chart>
</ng-container>
NazliTb commented 2 years ago

For me am using Vue still trying to figure out a way through

@DennisMwongera did you find a solution in Vue so far ? I am also having this issue where I have to resize the browser to be able to see my chart/data. If you or anyone else found a way through it for Vue please share it here. Thank you.

Bouafia19 commented 2 years ago

update the whole chart object for both options and series like this: updateCharte(categories, data){ this.chartOptions = { ...this.chartOptions, xaxis: { ...this.chartOptions.xaxis, categories: categories } }

        this.chartSeries = [{
            ...this.chartSeries,
            data: data
        }]
    },
BayBreezy commented 2 years ago

In order to get my charts to render after I leave a page and return, I had to use setTimeout in the mounted hook in Nuxt 3.

<script setup>
    const setChart = ref(false);
    onMounted(() => {
        setTimeout(() => {
            this.setChart = true;
        }, 100);
    });
</script>

Then in the template, I use v-if

<div v-if="setChart" class="grid grid-cols-1 lg:grid-cols-2 gap-10">
    <ChartBar />
       <ChartColumn />
</div>

package versions

"dependencies": {
    "@headlessui/vue": "^1.6.7",
    "apexcharts": "^3.35.4",
    "vue3-apexcharts": "^1.4.1"
  }
mhkarimi1383 commented 2 years ago

I got it to work by triggering window.resize manually after updating series:

window.dispatchEvent(new Event('resize'))

I have put this into mounted function of chart worked!! but ResetZoom is not working...

fernandolangaro commented 1 year ago

For those using Nuxt3 and vue3-apexcharts, that's how I choose to make it work. I added a :key prop to my apexchart component

<apexchart
    id="consultasChart"
    :key="renderChart"
    height="300"
    type="bar"
    :options="chartOptions"
    :series="series"
  />

And then I set it to update on mounted event

const renderChart = ref(0)
onMounted(() => {
  setTimeout(() => { renderChart.value++ }, 100)
})

I made it this way because I think it is better then using a v-if condition that will make your page renders first with an empty space and then, just later, suddenly render your apexchart. It is kinda ugly. Hope my solution helps! 🚀

GabyRibeiroCode commented 1 year ago

I am facing the same problem, please could you reopen the issue. I have tried many solutions including resize. My versions are apexcharts 3.36.0 and ng-apexcharts 1.7.4.

rodpatulski commented 1 year ago

In my case the resizing doesn't work. So I found another solution using "watch" as below. hope my solution be help

<apexchart :key="apexKey"  :serises="chartData" ~~~/>  

watch:{
   chartData:{
      deep: true,
      handler() {
        this.apexKey++
      },
    }

What's this 'watch' thing? It's not part of apexchart docs.

Arabath commented 1 year ago

La solucion anterior funciona de maravillas, pero actualiza a una grafica standard, y no respeta los seteos del data. Por ejemplo , si queremos cambiar los colores, tamaño del grafico serado o ocultar los legend que aparecen al lado de la grafica. Hay alguna solucion

ianyxtan commented 1 year ago

Thanks, I tried a similar approach (new_data) but it didn't work with apexcharts v3.30.0

you have to manually trigger key change testKey++ after you load options and series.

you can try refresh too. like this

<apexchart ref="myChart"/>

manually, somewhere in your method this.$refs.myChart.refresh()

Worked like a charm. Thanks for sharing!

anantgna commented 1 year ago

This issues exists still now, pleases resolve this.

EdwinJMataH commented 1 year ago

En mi caso hago uso de Vue 3 y los datos pasan a apexchart desde un store de pinia. La forma en como evito ese problema es haciendo un v-if y verificando que haya información en la variable, muestro un ejemplo en rasgos generales de como esta el código.

  import { useDashboardStore } from 'La ruta';
  const useStore = useDashboardStore();

  <div v-if="useStore.totales.length > 0"> 
      <VueApexCharts
         //otros atributos
         :series="useStore.totales"
       />
 </div> 
sujith-sairam commented 1 year ago

I am facing this issue recently when I resize the window the chart works properly or else its not working in angular

smitsonani77 commented 1 year ago

@sujith-sairam if you get any solution in angular then please post here.

sujith-sairam commented 1 year ago

@sujith-sairam if you get any solution in angular then please post here.

I found the solution . I tried to render the chart before it is being assigned to the property chartOptions .Try this solution in your html template

            <ng-container *ngIf="chartOptions">
                      <apx-chart
                        [series]="chartOptions.series"
                        [chart]="chartOptions.chart"
                        [dataLabels]="chartOptions.dataLabels"
                        [plotOptions]="chartOptions.plotOptions"
                        [xaxis]="chartOptions.xaxis"
                        [stroke]="chartOptions.stroke"
                      ></apx-chart>
                    </ng-container>
ujaandas commented 1 year ago

I'm using React and I have a useEffect() which plots the graph, and it runs anytime the props are changed (ie; the data being fed into the graph) - tried the window resize fix but it only works half the time, any other ideas?

IlCallo commented 1 year ago

Some notes and investigation on this:

  • The component doesn't initially resize automatically. After resizing the window, the apexcharts instance started auto-resizing as expected. This means that something is breaking during apexcharts instantiation, but a window resize fixes it.
  • I performed a full repo search and checked out other occurrences of redrawOnParentResize. I found it's used into _parentResizeCallback. I did a full repo search for that and I found out it's assigned to parentResizeHandler property. I searched where that is used and I found this line addResizeListener(this.el.parentNode, this.parentResizeHandler) right after window.addEventListener('resize', this.windowResizeHandler). Since the latter is working as expected, the problem is either the first or last parameter of the former
  • since a window resize fixes the problem, we can probably understand something more about it by checking out the _windowResizeHandler. Digging deeper, we can see that it destroys and recreates the whole Apexchart instance, so the problem most probably lies into a problem with the first apexchart instance inner state/context
  • addResizeListener seems to be the problem somehow
  • if this.el.parentNode is the cause, this may be a case of detached DOM element
  • sometimes it may happen that a DOM element is replaced by a new DOM element (e.g. due to a redraw of the whole DOM tree), but a reference to the previous DOM element isn't updated for some reason. Since DOM elements are nothing more than plain JS objects describing the elements themselves, they retain all the references and properties as if they are still attached. This also cause a memory leak, since JS garbage collector can't freeup the memory for objects which are still referenced somewhere
  • if this.parentResizeHandler is the cause, it could be a problem of apexchart internal state misalignment as well, since it's assigned as this._parentResizeCallback.bind(this) and thus bind to the current apexchart instance context
  • I did some tests and discovered that the this.el.parentNode seem to match before and after the window resize event, as well as their parents, so the problem doesn't seem to be a detached DOM node, we're probably looking at an out of sync apexchart instance internal state problem
  • manually forcing a chartRef.refresh() upon onMounted reveals that the internal state reference seems to be null, another hint to initialization problems

I stopped my research here, but the problem probably relies on how vue-apexcharts wraps the apexcharts instance and the order of the instructions executed to do so I'd suggest to port the component to Composition API to get a better DX in pin-pointing the root cause

smitsonani77 commented 1 year ago

Can anyone guide me for light/dark theme implementation on dashboard in angular. Like based on theme I want change the color of all the charts available on dashboard.

On Fri, 22 Sep, 2023, 8:07 pm Paolo Caleffi, @.***> wrote:

Some notes and investigation on this:

  • The component doesn't initially resize automatically. After resizing the window, the apexcharts instance started auto-resizing as expected. This means that something is breaking during apexcharts instantiation, but a window resize fixes it.
  • I performed a full repo search and checked out other occurrences of redrawOnParentResize. I found it's used into _parentResizeCallback. I did a full repo search for that and I found out it's assigned to parentResizeHandler property. I searched where that is used and I found this line addResizeListener(this.el.parentNode, this.parentResizeHandler) right after window.addEventListener('resize', this.windowResizeHandler). Since the latter is working as expected, the problem is either the first or last parameter of the former
  • since a window resize fixes the problem, we can probably understand something more about it by checking out the _windowResizeHandler. Digging deeper, we can see that it destroys and recreates the whole Apexchart instance, so the problem most probably lies into a problem with the first apexchart instance inner state/context
  • addResizeListener seems to be the problem somehow
  • if this.el.parentNode is the cause, this may be a case of detached DOM element
  • sometimes it may happen that a DOM element is replaced by a new DOM element (e.g. due to a redraw of the whole DOM tree), but a reference to the previous DOM element isn't updated for some reason. Since DOM elements are nothing more than plain JS objects describing the elements themselves, they retain all the references and properties as if they are still attached. This also cause a memory leak, since JS garbage collector can't freeup the memory for objects which are still referenced somewhere
  • if this.parentResizeHandler is the cause, it could be a problem of apexchart internal state misalignment as well, since it's assigned as this._parentResizeCallback.bind(this) and thus bind to the current apexchart instance context
  • I did some tests and discovered that the this.el.parentNode seem to match before and after the window resize event, as well as their parents, so the problem doesn't seem to be a detached DOM node, we're probably looking at an out of sync apexchart instance internal state problem
  • manually forcing a chartRef.refresh() upon onMounted reveals that the internal state reference seems to be null, another hint to initialization problems

I stopped my research here, but the problem probably relies on how vue-apexcharts wraps the apexcharts instance and the order of the instructions executed to do so

— Reply to this email directly, view it on GitHub https://github.com/apexcharts/vue-apexcharts/issues/185#issuecomment-1731535607, or unsubscribe https://github.com/notifications/unsubscribe-auth/ATHNSFGVDQHLOCV6WCJXMYDX3WPDVANCNFSM4JXSTYBA . You are receiving this because you commented.Message ID: @.***>

IlCallo commented 1 year ago

@smitsonani77 your question have nothing to do with this issue, please do not post it here