Search code examples
vue.jsvue-chartjs

Is it possible to dynamically add chart type in the extends: property, based on props from parent component?


I have a vue chartjs component which imports the whole vue-chartjs library. My idea is, is it possible to somehow pass the type of the chart which I want and add it to the 'extends: VueCharts.charttype?.' In the example I provide it extends the VueCharts.Line, I need this property to be dynamically interpolated, passed from props. Is it possible this charttype to come from a parent props dynamically and how?

<script>
import { VueCharts } from "vue-chartjs";

export default {
  extends: VueCharts.Line,
  props: ["chartdata", "options"],
  mounted() {
    this.renderChart(this.chartdata, this.options);
  }
}
</script>
<style scoped>

</style>

Solution

  • since extends the same as mixins, you need to pass a dynamic mixin, in order to do that you need two components, imagine we have component ChartWrapper :

    <template>
      <div>
        <div>{{ chartType }}</div>
        <chart :chart-data="datacollection"/>
      </div>
    </template>
    
    <script>
    import Chart from "./Chart";
    import { VueCharts, mixins } from "vue-chartjs";
    const { reactiveProp } = mixins;
    export default {
      name: "ChartWrapper",
      components: {
        Chart
      },
      props: {
        chartType: {
          type: String,
          required: true
        }
      },
      data() {
        return {
          datacollection: {
            labels: [this.getRandomInt(), this.getRandomInt()],
            datasets: [
              {
                label: "Data One",
                backgroundColor: "#f87979",
                data: [this.getRandomInt(), this.getRandomInt()]
              },
              {
                label: "Data One",
                backgroundColor: "#f87979",
                data: [this.getRandomInt(), this.getRandomInt()]
              }
            ]
          }
        };
      },
      methods: {
        getRandomInt() {
          return Math.floor(Math.random() * (50 - 5 + 1)) + 5;
        }
      },
      created() {
        if (this.chartType) {
          Chart.mixins = [reactiveProp,VueCharts[this.chartType]];
        }
      }
    };
    </script>
    

    this component takes chartType as a prop, and I import all charts as VueCharts in top of the script ==> 1

    second component:

    <script>
    export default {
      props: ["options"],
      mounted() {
        // this.chartData is created in the mixin.
        // If you want to pass options please create a local options object
        this.renderChart(this.chartData, this.options);
      }
    };
    </script>
    

    the second component just has options props, and renderChart function invoked. ==> 2

    What is happening?

    the ChartWrapper component receives the chart type by chartType prop, in the created hook, if chartType exist, assign the chart(resolved by VueCharts[this.chartType]) to Chart component as a mixin in addition to reactiveProp, I also pass the chart data to Chart component.

    in the end, call the ChartWrapper component:

    <ChartWrapper chartType="Bar"/>
    

    Live example on code sandbox: https://codesandbox.io/s/vue-template-w9r8k