Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically changing chart types with Vue Chart.js

I'm trying to use Vue Chart.js to implement a chart selector to visualise various data.

Structure of application:

  • ChartPicker.vue (allow user to pick chart, create data, use dynamic component key to re-render component)
    • ChartWrapper.vue (receives props and passes them on, creates mixin for dynamic chart type)
      • ChartRender.vue (simply renders chart)

In the chart render component you usually you need to do 'extends: Bar', 'extends: Line' etc, therefore, requiring a ChartRender component type for each chart type. I found a neat solution that passes in the chart type to the chart mixins, then the final chart render makes no reference to chart type (not quite clear how this works even after looking at vue-chart.js code). This is the example I based my code on (it has no chart type selection):

https://codesandbox.io/s/vue-template-original-1czfi

So, I tried to extend functionality of that example to add a chart selector. It's working to an extent on chart type change: data changes, components re-render but the chart type doesn't change (even though it's being passed to the mixin dynamically)

I have a running example here:

https://codesandbox.io/s/vue-chart-issue-v2-twg3o

I've spent nearly a week trying to figure this out with no joy. I could create a workaround to use a separate ChartRender component for each chart type (e.g. ChartRenderBar, ChartRenderLine etc) but it moves away from DRY, so would rather not.

If anybody could help, I'd be VERY appreciative,

like image 592
Rich Love Avatar asked May 21 '26 22:05

Rich Love


1 Answers

It is possible to dynamically update your chart type with vue-chartjs. The way I did it is by accessing the options in the chart itself and replacing it with the prop I get in which says which chart type it should become and then do an update on the chart. It is not the most elegant solution but it works.

<script>
import { Line, mixins } from 'vue-chartjs';
const { reactiveProp } = mixins;

export default {
  extends: Line,
  name: "LineChart",
  mixins: [reactiveProp],
  props: {
    options: { type: Object },
    chartType: { type: String }
  },
  mounted () {
    this.renderChart(this.chartData, this.options);
  },
  watch: {
    options: {
      deep: true,
      handler () {
        this.$data._chart.options = this.options;
        this.updateChart();
      }
    },

    chartType (newVal) {
      this.$data._chart.config.type = newVal;
      this.updateChart()
    }
  },
  methods: {
    updateChart () {
      this.$data._chart.update();
    },
  }
}
</script>
like image 98
LeeLenalee Avatar answered May 24 '26 18:05

LeeLenalee



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!