It would be really nice to have a typescript sample. Having hard time rendering the chart using typescript and vue-chartjs
Well I am not using typescript and have no experience in it. You could ask on stackoverflow, maybe someone can provide an example.
@jayalakshmis
Just write your own and send a pull request... It works easy as transcripting this file https://github.com/apertureless/vue-chartjs/blob/develop/src/BaseCharts.js with https://github.com/kaorun343/vue-property-decorator syntax.
Use it, it works, though I haven't figured out a way to pass default props in ts
plot.ts
import { Component } from "vue-property-decorator";
import Vue from "vue";
import template from "./plot.vue";
import Chart, { ChartData, ChartOptions } from "chart.js";
@Component({
mixins: [template],
props: {
chartId: String,
width: Number,
height: Number,
cssClasses: String,
styles: Object,
plugins: Array,
chartType: String,
data: Object,
options: Object
}
})
export default class Plot extends Vue {
chartId: string;
width: number;
height: number;
cssClasses: string;
chartType: string;
styles: { [key: string]: string };
plugins: Array<any>;
data: ChartData;
options: ChartOptions;
_chart: Chart | null = null;
_plugins = this.plugins;
addPlugin(plugin: any) {
this._plugins.push(plugin);
}
renderChart(data: any, options: any) {
let canvas: any = this.$refs.canvas;
this._chart = new Chart(
canvas.getContext("2d"), {
type: this.chartType,
data: data,
options: options,
plugins: this._plugins
}
);
}
mounted () {
this.renderChart(this.data, this.options);
}
beforeDestroy() {
if (this._chart) {
this._chart.destroy();
}
}
}
plot.vue
<template>
<div :style=styles :class=cssClasses>
<canvas :id=chartId :width=width :height=height ref="canvas"/>
</div>
</template>
@jayalakshmis
is this now resolved?
closed due to inactivity
@BenBBear thank you for the example but I don't understand, you don't use the "vue-chartjs" module. Could you explain why please?
On my side I tried to extend my component with:
@Component({})
export default class MyChart extends Line {
But this is not working. I guess the "Line" class doesn't implement basic "Vue" class.
EDIT:
The error:
vue-router.esm.js?8c4f:1905 TypeError: Super expression must either be null or a function
at _inherits (inherits.js?b9a2:4)
at eval (MyChart.vue?a70c:10)
That's weird because accordingly to this PR: https://github.com/apertureless/vue-chartjs/pull/378/files it should work due to inheritance: MyChart < Line < BaseChart < Vue
@sneko
I guess @BenBBear was not using the vue-chartjs
module, because back in that time it does not have the typescript typings included.
However, I have still no experience in typescript and cannot really help here 🙈
@sneko this PR just adds the types but not the functionality.
@apertureless the thing is that the decorator @Component
is basically calling the constructor of BaseCharts.js
, which is not existent atm, as it exports a plain object (this is also unrelated to TypeScript). I can try to fix this in a PR.
EDIT:
Seems like it possible to pass it as generic:
import { Line } from 'vue-chartjs';
@Component
export default class Plot extends Vue<Line> {}
The suggested solution using extends Vue<Line> {}
didn't work for me but I managed to get this to work by defining an internal chart component as vanilla JS and importing it into a TS component. A bit of a hack but not too much really.
@fratuz610 can you post your solution?
Yes apologies I have been a bit lazy with my previous comment :)
Basically I created a dumb InternalChart.js
component in JS
import { Line, mixins } from 'vue-chartjs'
const { reactiveProp } = mixins
export default {
extends: Line,
props: ['chartData', 'options'],
mixins: [reactiveProp],
mounted () {
this.renderChart(this.chartData, this.options);
}
}
which is used by a ReadingChart.ts
component where I put the business logic:
<template>
<div class="reading-chart">
...
<InternalChart
:width="chartWidth"
:height="chartHeight"
:chart-data="chartData()"
:options="chartOptions()"
/>
...
</div>
</template>
<script lang="ts">
import { Component, Vue, Prop, Watch } from 'vue-property-decorator';
...
// you need to ts-ignore this line or TS will complain about the lack of type definitions
// there could be a more elegant solution though
//@ts-ignore
import InternalChart from '@/components/InternalChart.js';
@Component({
components:{
InternalChart,
...
}
})
export default class ReadingChart extends Vue {
chartWidth:number = 636;
chartHeight:number = 500;
...
async mounted() {
this.refreshData();
}
async refreshData() {
// do an API call here and touch properties that will cause chartData() and chartOptions() to be called
// Because of the reactiveProp mixin inside InternalChart.js, the chart will update automagically :)
}
chartData(): object {
// chart js DATA object. See https://www.chartjs.org/docs/latest/getting-started/usage.html
return {
labels: ...
datasets: ...
}
}
chartOptions(): object {
// chart js OPTIONS object. See https://www.chartjs.org/docs/latest/getting-started/usage.html
return {}
}
}
</script>
<style scoped lang="scss">
.reading-chart {
display: flex;
width: 100%;
height: 100%;
justify-content: space-around;
}
...
</style>
They both sit in the same folder but this is not mandatory of course
@fratuz610 Thanks for the post!
@fratuz610 Thanks a lot !
Is there any plans to implement the missing constructor in BaseCharts.js
? It would be great if we can avoid having to rely on the proposed hack.
@davidsandoz Feel free to submit a PR.
As I am not using typescript, I am missing the experience and knowledge and currently do not have time to research & learn TS.
@apertureless, tbh, I'm not really sure what needs to be changed exactly.
If @JPeer264, who raised the issue in https://github.com/apertureless/vue-chartjs/issues/313#issuecomment-442811446, has some idea and can give some hints on how to proceed, I can try to come up with a PR.
FYI: Vue 3 will be TS based. Vanilla JS is becoming the exception.
@fratuz610
Vue.js v3 core will be rewritten in TS. Currently they are using flow.
However, this will not affect the way you are using vue.
And I wouldn't support the claim that "Vanilla JS is becoming the exception."
PR opened #484
@davidsandoz I meant with my comment, that the Bar
, Line
or any other charts are no classes, which on the other hand the types assumes.
So it works in Typescript with the types, as it extends the correct type class. But the implementation is a basic function which cannot be extended (class extends
). I think it could work with a kinda class wrapper like:
@Component({
extends: Bar,
})
class BarClass extends Vue { }
So then the class can be extended and the types just have to be added to BarClass
instead of Bar
(which is not a class):
@Component
export default class MyChart extends BarClass {
}
@JPeer264 I get an error from your example in typescript 3.4.1
I've had luck using mixins instead:
@Component
export default class CommitChart extends Mixins(Bar) {
mounted () {
// Overwriting base render method with actual data.
this.renderChart({
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
datasets: [
{
label: 'GitHub Commits',
backgroundColor: '#f87979',
data: [40, 20, 12, 39, 10, 40, 39, 80, 40, 20, 12, 11]
}
]
})
}
}
Oh yeah the mixin worked fine.
@luciano7
Mixins work at runtime but the compiler does not show any props and methods from Bar
. Also I get the following warning. Any idea why?
@alexeigs is there more to that error message that is not in your screenshot?
What worked for me after trying like a dozen solutions:
@Component({
extends: Line,
})
export default class DurationsChart extends Vue {
public renderChart!: (chartData: any, options: any) => void;
mounted() {
...
}
}
this worked, finally https://github.com/apertureless/vue-chartjs/issues/495#issuecomment-663034152
Most helpful comment
@JPeer264 I get an error from your example in typescript 3.4.1

I've had luck using mixins instead: