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

Closed vhniii closed 1 month 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

NigmetAli commented 1 year ago

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

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

Worked for me, thanks.

mahadih-gg commented 1 year ago

I fix this issue in react.

The following code should be given in the component in which the chart has been made.

  useEffect(() => {
    window.dispatchEvent(new Event('resize'))
  },[])
Tepexic commented 8 months ago

In Vue 3, I managed to get around this issue by keeping the chart options and series as separate entities, changing the id and adding a watcher for changes on the data. Something like this:

<template>
  <VueApexCharts ref="chart" :options="options" :series="series" />
</template>

<script setup>
import VueApexCharts from 'vue3-apexcharts'
import { computed, ref, watch } from 'vue'

const props = defineProps({
  data: {
    type: Array,
    default: () => []
  }
})

const chart = ref(null)

const getChartSeries = () => {
  return {
    name: 'Data',
    data: props.data
  }
}
const getChartOptions = () => {
  return {
    chart: {
      id: `chart-${Math.random()}`,
      type: 'line',
      foreColor: '#333',
      theme: {
        mode: 'dark'
      }
    },
    series: [],
    xaxis: {
      labels: {
        rotate: -45
      }
    }
  }
}

const options = ref(getChartOptions())
const series = ref(getChartSeries())

const updateChart = (updatedOptions, updatedSeries) => {
  chart.value?.updateOptions(updatedOptions)
  chart.value?.updateSeries(updatedSeries)
}

watch(
  () => props.data,
  () => {
    series.value = getChartSeries()
    options.value = getChartOptions()
    updateChart(options.value, series.value)
  }
)
</script>
syed-rajib commented 7 months ago

Screenshot from 2024-03-21 21-38-54 when dynamically load data in the chart , column not showing as perfectly with yaxis data label . as you can see when hover it value is showing 1182 but Problem is browse column not perfect as y-axis data labels .

here I am sharing codes.

       <apexchart
                ref="barChart"
                width="100%"
                type="bar"
                :options="itemBarChart"
                :series="[{ data: itemChartData }]"
              ></apexchart>

                itemBarChart: {
    chart: {
      type: "bar",
      height: 400,
      toolbar: {
        // show: false,
        show: true,
      tools: {
        download: true,
        selection: true,
        zoom: true,
        zoomin: true,
        zoomout: true,
        pan: true,
        reset: true | '<img src="/static/icons/reset.png" width="20">',
        customIcons: []
      },
      autoSelected: 'zoom'
      },
    },
    colors: ["#008FFB", "#FF4560", "#33B2DF", "#00E396"],
    plotOptions: {
      bar: {
        horizontal: false,
        columnWidth: "55%",
        endingShape: "rounded",
        dataLabels: {
  position: 'bottom'
}
      },
    },
    dataLabels: {
      enabled: false,
    },
    stroke: {
      show: true,
      width: 2,
      colors: ["transparent"],
    },
    xaxis: {
      categories: [
        "Browse",
        "Positive Rated",
        "Negative Rated",
        "Purchase",
      ],
      labels: {
        style: {
          colors: "#000000",
          fontSize: "14px",
          fontFamily: "Helvetica, Arial, sans-serif",
        },
      },
    },
    yaxis: {
logarithmic: true,  // Enable logarithmic scale
// tickAmount: 'dataPoints',  // Adjust the number of ticks for better visualization
// min: 1,  // Set the minimum value to 1 (or a small value close to your smallest data point)
// forceNiceScale: false  // Disable the nice scale to ensure we can use a logarithmic scale

}, fill: { opacity: 1, }, tooltip: { x: { formatter: function () { return ""; }, }, y: { formatter: function (val, { dataPointIndex, w }) { const label = w.globals.labels[dataPointIndex]; return ${label}: ${val}; }, title: { formatter: function () { return ""; }, }, }, followCursor: true, }, title: { text: "Items Counts", align: "center", margin: 20, style: { fontSize: "20px", fontFamily: "Helvetica, Arial, sans-serif", color: "#333333", }, }, responsive: [ { breakpoint: 768, options: { chart: { height: 300, }, xaxis: { labels: { style: { fontSize: "12px", }, }, }, yaxis: { min: 0, max: 100, labels: { style: { fontSize: "12px", }, }, }, title: { style: { fontSize: "16px", }, }, }, }, ], },

    itemChartData() {

  const x = [
    this.insights.kpi_summary.browse.total_browsed_items,
  this.insights.kpi_summary.ratings.total_positive_rated_items,
  this.insights.kpi_summary.ratings.total_negative_rated_items,
 this.insights.kpi_summary.purchase.total_purchased_items,
  ];
  if (x.length == 4){

    return x;
  }

},

anon-phantom commented 3 months ago

not familiar with vue, I was looking for a solution in ReactJS to update data series dynamically.

best way to do it is to use useState + useEffect for a functional component

const [records, setRecords] = useState([]);

useEffect(() => {
  setRecords({});
}, [records]);

const series = [
  {
    data: [...records],
    name: 'Records',
  },
];

...

return (
  <ReactApexChart
    id='records-chart'
    options={options}
    series={series}
    type='area'
    height='280px'
  />
);

or use componentDidMount if you were using a class component, following the same logic.

github-actions[bot] commented 1 month ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.