3

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,

1
  • Anyhow, you need to keep the component ready like ChartRenderBar, ChartRenderLine and switch between component, so I don't think you can go DRY here and of course, the that you pass as through props that can be dry. Commented Mar 27, 2020 at 16:49

2 Answers 2

3

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>
Sign up to request clarification or add additional context in comments.

1 Comment

Didn't have to use all setup with mixins, but key was in these two lines: this.$data._chart.config.type = newVal; and this.$data._chart.update(); Thanx @LeeLenalee
1

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.

2 Comments

Thanks so much for the reply. It's a neat idea with the dynamic component, will perhaps use that. So it seems what I was trying to achieve is not really possible and there will be a fair amount of code duplication. It's a relief I can stop 'banging my head against the wall now' :) Thanks again for taking the time to look 🙏🏼
Welcome my friend Good luck

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.