This question has been asked before at https://stackoverflow.com/questions/51022003/vue-chartjs-create-gradient-background-for-chart-from-child-component-canvas. However I think a lot of people would benefit from an example in the documentation somewhere.
The author in this article like me was 'confused' as to what was meant by "..pass in all data as props" . I still don't know what I need to do to get this working. My scenario is exactly the same as the author.
The actual reusable chart code is:
```import { Bar, mixins } from 'vue-chartjs';
export default {
extends: Bar,
gradient: null,
mixins: [mixins.reactiveProp],
props: ['chartData', 'options'],
mounted() {
var gradientStroke = this.$refs.canvas.getContext('2d').createLinearGradient(0, 230, 0, 50);
gradientStroke.addColorStop(1, 'rgba(253,93,147,0.8)');
gradientStroke .addColorStop(0, 'rgba(253,93,147,0)'); //blue colors
//I don't know what to do with it here. Because if the chart isn't reusable and I add my chartdata here it works fine. But I want it to be reusable
this.renderChart(this.chartData, this.options);
}
};
### Actual Behavior
Then in my parent code:
```this.myChartData = {
labels: labels,
datasets: [{
label: 'Name',
fill: true,
backgroundColor: '#ff5991',
hoverBackgroundColor: '#ff5991',
borderColor: '#ff5991',
borderWidth: 2,
borderDash: [],
borderDashOffset: 0.0,
data: chartdata
}]
};
Please can we add an example for this as I know this is for issues only but there isn't anyone or Gittur to talk to.
Many thanks
Well, if you want a reuseable chart, it depends on mulitple factors, because there are multiple ways of doing it.
The more generic the solution should be, the more complex it will get.
The questions are, what should be reuseable and configurable?
The easiest solution is if you just have a line chart for example with only one dataset. And the colors/gradients are fixed.
import {Line} from 'vue-chartjs'
export default {
extends: Line,
props: {
labels: {
type: Array,
default: () => ['A', 'B', 'C']
},
datalabel: {
type: String,
default: 'Downloads per Week'
},
chartdata: {
type: Array,
default: () => [100, 40, 106]
}
},
data () {
return {
gradient: null
}
},
mounted () {
this.gradient = this.$refs.canvas.getContext('2d').createLinearGradient(0, 0, 0, 450)
this.gradient.addColorStop(0, 'rgba(255, 0,0, 0.5)')
this.gradient.addColorStop(0.5, 'rgba(255, 0, 0, 0.25)');
this.gradient.addColorStop(1, 'rgba(255, 0, 0, 0)');
this.renderChart({
labels: this.labels,
datasets: [
{
label: this.datalabel,
borderColor: '#FC2525',
pointBackgroundColor: 'white',
borderWidth: 1,
pointBorderColor: 'white',
backgroundColor: this.gradient,
data: this.chartdata
}
]
}, {responsive: true, maintainAspectRatio: false})
}
}
This way, you can pass in your data, labels etc. and have a reuseable chart.
You could also make it a bit simpler if you use the rest/spread operator.
import {Line} from 'vue-chartjs'
export default {
extends: Line,
props: {
labels: {
type: Array,
default: () => ['A', 'B', 'C']
},
chartconfig: {
type: Object,
default: () => {
label: 'My Data',
borderColor: '#FC2525',
pointBackgroundColor: 'white',
borderWidth: 1,
pointBorderColor: 'white',
data: [10, 11, 12]
}
}
},
data () {
return {
gradient: null
}
},
mounted () {
this.gradient = this.$refs.canvas.getContext('2d').createLinearGradient(0, 0, 0, 450)
this.gradient.addColorStop(0, 'rgba(255, 0,0, 0.5)')
this.gradient.addColorStop(0.5, 'rgba(255, 0, 0, 0.25)');
this.gradient.addColorStop(1, 'rgba(255, 0, 0, 0)');
this.renderChart({
labels: this.labels,
datasets: [
{
...this.chartconfig
backgroundColor: this.gradient,
}
]
}, {responsive: true, maintainAspectRatio: false})
}
}
This way you are setting the backgroundColor gradient and the rest of the data and config comes over your vue props.
It becomes a bit more complicated if you want configurable gradients.
If you just want different colors you can pass in the gradient colors as props and then in your mounted() hook just reference them
this.gradient.addColorStop(0, '`${this.gradientColor1}`')
If you want more configuration you have to write a small generateGradient helper, which takes his data from props or a gradient Object which is a prop.
For example
// Example object with your configuration for your gradient.
const settings = {
gradientColorStops: 3,
colorStopValues: [0, 0.5, 1],
colorStopColors: ['rgba(...)', 'rgba(...)', 'rgba(...)']
}
...
props: {
gradient: {
type: Boolean,
default: true
}
gradientSettings: {
type: Object,
default: () => {}
}
}
....
mounted () {
if (this.gradient) {
this.generateGradient()
// in generateGradient you can iterate over the values you got passed in your gradientSettings for (let i = 0; i < this.gradientSettings.gradientColorStops; i++)
}
},
@apertureless this code looks great but to make i reactive do I need to add a watcher? BEcauseat the moment it doesn't update data when my api is finished making the call. If I hard code the values in the props on the chart component it works?
Well, you never mentioned any api calls ;)
You could just add a v-if="loaded" to your chart. So it only renders if your api call is finished
https://vue-chartjs.org/guide/#chart-with-api-data
However, please use stackoverflow for this kind of questions. The issues here are more for feature requests / bugs and not for "how do I do xxx"
OK I get it, I do apologise but there isn't much help there sometimes. Anyway this would still be beneficial to have in the docs though
I mean your code samples you gave me a few minutes ago not the v-if thing
Thanks anyway you have been most helpful and I appreciate the library a lot :)
Most helpful comment
Well, if you want a reuseable chart, it depends on mulitple factors, because there are multiple ways of doing it.
The more generic the solution should be, the more complex it will get.
The questions are, what should be reuseable and configurable?
The easiest solution is if you just have a line chart for example with only one dataset. And the colors/gradients are fixed.
This way, you can pass in your data, labels etc. and have a reuseable chart.
You could also make it a bit simpler if you use the rest/spread operator.
Chart with spread
This way you are setting the backgroundColor gradient and the rest of the data and config comes over your vue props.
It becomes a bit more complicated if you want configurable gradients.
If you just want different colors you can pass in the gradient colors as props and then in your
mounted()hook just reference themIf you want more configuration you have to write a small
generateGradienthelper, which takes his data from props or a gradient Object which is a prop.For example