I want to pass the data from Parent to GrandChild (which is Chart) with reactivity so I'm using props.
This is the Parent
The "kalkulator-data" component below is worked and it's used to adding data to Parent.
<template>
<div class="container">
<div class="row">
<kalkulator-data
:saldoAwal="saldoAwal"
:saldoTerpakai="saldoTerpakai"
:saldoAkhir="saldoAkhir"
:dataKategori="dataKategori"
:dataPengeluaran="dataPengeluaran"
@inputSaldo="saldoAwal = $event"
@inputPengeluaran="dataPengeluaran.push($event)">
</kalkulator-data>
<kalkulator-chart
:chartData="chartData"
:chartOptions="chartOptions">
</kalkulator-chart>
</div>
</div>
</template>
<script>
import Chart from './Bagian/Chart.vue';
import Data from './Bagian/Data.vue';
export default {
data(){
return {
saldoAwal : 0,
dataPengeluaran : [{ kategori : 'Abi', nominal : 12}, { kategori : 'Ilham', nominal : 13}],
dataKategori : [
'Makan dan Minum',
'Berbelanja',
'Perlengkapan Rumah',
'Transportasi',
'Kendaraan',
'Gaya Hidup dan Hiburan',
'Komunikasi',
'Pengeluaran dan Finansial',
'Investasi',
],
chartOptions : {responsive: true, maintainAspectRatio: false}
}
},
computed : {
saldoTerpakai(){
var saldoPakai = 0;
for(var data of this.dataPengeluaran){
saldoPakai += parseInt(data.nominal);
}
return saldoPakai;
},
saldoAkhir(){
return this.saldoAwal - this.saldoTerpakai;
},
getRandomColor(){
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
},
chartLabels(){
var chartLabels = [];
for (var data of this.dataPengeluaran ){
chartLabels.push(data.kategori);
// backgroundColor.push(this.getRandomColor);
};
return chartLabels;
},
chartId(){
var chartData = [];
for (var data of this.dataPengeluaran ){
chartData.push(parseInt(data.nominal));
// backgroundColor.push(this.getRandomColor);
};
return chartData;
},
chartData(){
return {
labels: this.chartLabels,
datasets: [
{
label: 'Data One',
backgroundColor: '#f87979',
data: this.chartId
}
]
}
}
},
methods : {
},
components : {
'kalkulator-data' : Data,
'kalkulator-chart' : Chart
},
}
</script>
This is the Child
<template>
<div class="col-sm-6">
<div class="row">
<h1 class="text-center">Struktur Pengeluaran</h1>
<chart-comp
:chartData="chartData"
:chartOptions="chartOptions">
</chart-comp>
</div>
</div>
</template>
<script>
import chartComp from './Chart-Data.js'
export default{
props : ['chartData', 'chartOptions'],
components : {
'chart-comp' : chartComp
}
}
</script>
And this the GrandChild which is Chart
import {Bar} from 'vue-chartjs'
export default Bar.extend({
props : ['chartData', 'chartOptions'],
computed : {
renderChart(){
this.renderChart(this.chartData, this.chartOptions);
}
},
mounted () {
this.renderChart;
}
})
I'm using computed to keep the reactivity when I'm added data, but It said in console :
app.js:5366 [Vue warn]: Error in mounted hook: "RangeError: Maximum call stack size exceeded"
found in
---> <ChartComp>
<KalkulatorChart> at C:\xampp\htdocs\SemuaOkee-Laravel\resources\assets\js\components\Bagian\Chart.vue
<Kalkulator> at C:\xampp\htdocs\SemuaOkee-Laravel\resources\assets\js\components\Kalkulator.vue
<Root>
warn @ app.js:5366
handleError @ app.js:5451
callHook @ app.js:7490
insert @ app.js:8315
invokeInsertHook @ app.js:10143
patch @ app.js:10308
Vue._update @ app.js:7248
updateComponent @ app.js:7371
get @ app.js:7710
Watcher @ app.js:7693
mountComponent @ app.js:7375
Vue$3.$mount @ app.js:12503
Vue$3.$mount @ app.js:14602
Vue._init @ app.js:8942
Vue$3 @ app.js:9027
(anonymous) @ app.js:29926
__webpack_require__ @ app.js:20
(anonymous) @ app.js:29888
__webpack_require__ @ app.js:20
(anonymous) @ app.js:63
(anonymous) @ app.js:66
app.js:5455 RangeError: Maximum call stack size exceeded
at Watcher.evaluate (app.js:7809)
at VueComponent.computedGetter [as renderChart] (app.js:8064)
at VueComponent.renderChart (app.js:61047)
at Watcher.get (app.js:7710)
at Watcher.evaluate (app.js:7810)
at VueComponent.computedGetter [as renderChart] (app.js:8064)
at VueComponent.renderChart (app.js:61047)
at Watcher.get (app.js:7710)
at Watcher.evaluate (app.js:7810)
at VueComponent.computedGetter [as renderChart] (app.js:8064)
When I'm still not added the data, it's work perfectly ( that's why I'm hardcoded two objects in Parent to test my Chart in the beginning), but when I'm added a data it's got an error.
In other words, It's work on static but not with dynamic data.
In your grandchild component, you have defined a computed property renderChart
which returns this.renderChart
. This is what is causing the Maximum call stack size error.
You should just call the renderChart
method in the mounted
hook:
import { Bar } from 'vue-chartjs'
export default Bar.extend({
props: ['chartData', 'chartOptions'],
mounted() {
this.renderChart(this.chartData, this.chartOptions);
}
})
If you need the chart data to be reactive, vue-chartjs provides an admittedly goofy way to specify that using a mixin:
import { Bar, mixins } from 'vue-chartjs'
export default Bar.extend({
props: ['chartData', 'chartOptions'],
mixins: [mixins.reactiveProp],
mounted() {
this.renderChart(this.chartData, this.chartOptions);
}
})
Here's the vue-chartjs documentation on using reactive data.