Currently, I am delving into the world of VueJs and experimenting with Chart.js (https://github.com/apertureless/vue-chartjs). I attempted to make a doughnut chart reactive, but I achieved this using the ref property which I suspect may not be the best practice. My main query is whether it's true that avoiding $refs is advisable in such scenarios.
My initial hurdle was the lack of understanding about mixins. The only example I found on how to use vue-chartjs reactively included its use (https://github.com/apertureless/vue-chartjs/blob/master/src/examples/ReactiveExample.js can be referred for context). To overcome this, I created a method called updateData within my Vue component which essentially resets the chartData and then sets it to the prop data. Here is a snippet of my code:
chart.blade.php (web view):
<html>
<head>
<meta charset="utf-8">
<title>Testchart</title>
<link rel="stylesheet" href="css/app.css">
</head>
<body>
<div id="app">
<h1>Testchart</h1>
<doughnut :data="doughnut_data" :options="doughnut_options" ref="chart"></doughnut>
<button-reduce v-on:numberreduced="reduce"></button-reduce>
</div>
<script src="js/app.js" charset="utf-8"></script>
</body>
</html>
app.js:
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
Vue.component('doughnut', require('./components/testDoughnut.vue'));
Vue.component('button-reduce', require('./components/button.vue'));
const app = new Vue({
el: '#app',
data: {
doughnut_data: {
labels: ['VueJs', 'EmberJs', 'ReactJs', 'AngularJs'],
datasets: [
{
backgroundColor: [
'#41B883',
'#E46651',
'#00D8FF',
'#DD1B16'
],
data: [40, 20, 80, 10]
}
]
},
doughnut_options: {
responsive: true,
maintainAspectRatio: false
}
},
methods: {
reduce() {
this.doughnut_data.datasets[0].data[2] = this.doughnut_data.datasets[0].data[2] - 5;
this.$refs.chart.updateData();
}
}
});
Last but not least, let me introduce my Vue component testDoughnut.vue
<script>
import { Doughnut, mixins } from 'vue-chartjs'
export default Doughnut.extend({
mixins: [mixins.reactiveData],
props: ["data", "options"],
data() {
return {
chartData: ''
}
},
created() {
this.updateData();
},
mounted () {
this.renderChart(this.chartData, this.options)
},
methods: {
updateData() {
this.chartData = {}; // without this step, it does not work (no reactive behaviour). Why is this necessary?
this.chartData = this.data;
}
}
})
</script>
The following questions have emerged:
- (from above): Is steering clear of $refs indeed recommended?
- Why is it challenging to directly update chartData from my webview? Using
:chartData="doughnut_data"
did not yield results, instead I had to employ a custom prop 'data' - In my testDoughnut.vue, why is it essential to first reset chartData to an empty JSON object before assigning it to this.data? This seemed unnecessary based on my experience in desktop development (C#) where I could just write
this.chartData = this.data
. - Is there a more efficient alternative to handling this issue rather than relying on ref as I have done?