Rich Love
Rich Love

Reputation: 56

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:

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,

Upvotes: 3

Views: 4162

Answers (2)

Kamal Alhomsi
Kamal Alhomsi

Reputation: 671

in Vuejs, it is not possible to change mixins after the component being created, and because of this I've used a wrapper component in my other solution, so I can pass a mixin dynamically before the component being created, but unfortunately, there is no way to have some kind of reactive mixin.

my solution for you current situation would be something like that:
https://codesandbox.io/s/vue-template-y5wsw

in the above solution, I have created two components, BarChart and LineChart
to switch between those dynamically, I am using one of the most awesome features in vuejs, Dynamic Component

and of course to avoid duplicating the data source, you can use vuex to share data between multiple components, or you can have the data in the parent page and access your dataset or options like

this.$parent['whatever data property in your parent component']

Hope you found this helpful.

Upvotes: 1

LeeLenalee
LeeLenalee

Reputation: 31341

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>

Upvotes: 3

Related Questions