Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to vue3 #755

Merged
merged 12 commits into from
Mar 10, 2022
Prev Previous commit
Next Next commit
feat: migrate basecharts to vue3
add vue3 to basecharts.js, remove mixins

BREAKING CHANGE: remove mixins
thabarbados committed Mar 2, 2022

Verified

This commit was signed with the committer’s verified signature.
heemankv Heemank Verma
commit 60e65ffa11345992e9ab30b255949ff16b13c389
207 changes: 156 additions & 51 deletions src/BaseCharts.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
Chart,
Chart as ChartJS,
BarController,
BubbleController,
DoughnutController,
@@ -10,29 +10,28 @@ import {
ScatterController
} from 'chart.js'

export function generateChart(chartId, chartType, chartController) {
return {
render: function (createElement) {
return createElement(
'div',
{
style: this.styles,
class: this.cssClasses
},
[
createElement('canvas', {
attrs: {
id: this.chartId,
width: this.width,
height: this.height
},
ref: 'canvas'
})
]
)
},
import {
defineComponent,
ref,
h,
onMounted,
onBeforeUnmount,
watch,
isProxy,
toRaw
} from 'vue'

export const generateChart = (chartId, chartType, chartController) =>
defineComponent({
props: {
chartData: {
type: Object,
required: true
},
chartOptions: {
type: Object,
default: () => {}
},
chartId: {
default: chartId,
type: String
@@ -50,57 +49,163 @@ export function generateChart(chartId, chartType, chartController) {
default: ''
},
styles: {
type: Object
type: Object,
default: () => {}
},
plugins: {
type: Array,
default() {
return []
}
}
},
data() {
return {
_chart: null
type: Object,
default: () => {}
}
},
created() {
Chart.register(chartController)
},
methods: {
renderChart(data, options) {
if (this.$data._chart) {
this.$data._chart.destroy()
setup(props, context) {
ChartJS.register(chartController)

const _chart = ref(null)
const canvasEl = ref(null)

function renderChart(data, options) {
if (_chart.value !== null) {
toRaw(_chart.value).destroy()
}

if (!this.$refs.canvas) {
if (canvasEl.value === null) {
throw new Error(
'Please remove the <template></template> tags from your chart component. See https://vue-chartjs.org/guide/#vue-single-file-components'
)
}

const chartOptions = options

if (this.plugins.length > 0) {
for (const plugin of this.plugins) {
chartOptions.plugins = { ...chartOptions.plugins, ...plugin }
}
if (
typeof props.plugins !== 'undefined' &&
Object.keys(props.plugins).length > 0
) {
chartOptions.plugins = { ...chartOptions.plugins, ...props.plugins }
}

this.$data._chart = new Chart(this.$refs.canvas.getContext('2d'), {
_chart.value = new ChartJS(canvasEl.value.getContext('2d'), {
type: chartType,
data: data,
options: chartOptions
})
}
},
beforeDestroy() {
if (this.$data._chart) {
this.$data._chart.destroy()

function chartDataHandler(newValue, oldValue) {
const newData = isProxy(newValue) ? toRaw(newValue) : { ...newValue }
const oldData = isProxy(oldValue) ? toRaw(oldValue) : { ...oldValue }

if (Object.keys(oldData).length > 0) {
const chart = toRaw(_chart.value)

// Get new and old DataSet Labels
const newDatasetLabels = newData.datasets.map(dataset => {
return dataset.label
})

const oldDatasetLabels = oldData.datasets.map(dataset => {
return dataset.label
})

// Stringify 'em for easier compare
const oldLabels = JSON.stringify(oldDatasetLabels)
const newLabels = JSON.stringify(newDatasetLabels)

// Check if Labels are equal and if dataset length is equal
if (
newLabels === oldLabels &&
oldData.datasets.length === newData.datasets.length
) {
for (const [i, dataset] of newData.datasets.entries()) {
// Get new and old dataset keys
const oldDatasetKeys = Object.keys(oldData.datasets[i])
const newDatasetKeys = Object.keys(dataset)

// Get keys that aren't present in the new data
const deletionKeys = oldDatasetKeys.filter(key => {
return key !== '_meta' && newDatasetKeys.indexOf(key) === -1
})

for (const deletionKey of deletionKeys) {
delete chart.data.datasets[i][deletionKey]
}

// Update attributes individually to avoid re-rendering the entire chart
for (const attribute in dataset) {
if (Object.prototype.hasOwnProperty.call(dataset, attribute)) {
chart.data.datasets[i][attribute] = dataset[attribute]
}
}
}

if (Object.prototype.hasOwnProperty.call(newData, 'labels')) {
chart.data.labels = newData.labels
context.emit('labels:update')
}

if (Object.prototype.hasOwnProperty.call(newData, 'xLabels')) {
chart.data.xLabels = newData.xLabels
context.emit('xlabels:update')
}

if (Object.prototype.hasOwnProperty.call(newData, 'yLabels')) {
chart.data.yLabels = newData.yLabels
context.emit('ylabels:update')
}

chart.update()
context.emit('chart:update')
} else {
if (chart !== null) {
chart.destroy()
context.emit('chart:destroy')
}

renderChart(props.chartData, props.options)
context.emit('chart:render')
}
} else {
if (_chart.value !== null) {
toRaw(_chart.value).destroy()
context.emit('chart:destroy')
}

renderChart(props.chartData, props.options)
context.emit('chart:render')
}
}

watch(
() => props.chartData,
(newValue, oldValue) => chartDataHandler(newValue, oldValue),
{ deep: true }
)

onMounted(() => {
if (
'datasets' in props.chartData &&
props.chartData.datasets.length > 0
) {
renderChart(props.chartData, props.chartOptions)
}
})

onBeforeUnmount(() => {
if (_chart.value !== null) {
toRaw(_chart.value).destroy()
}
})

return () =>
h('div', { style: props.styles, class: props.cssClasses }, [
h('canvas', {
id: props.chartId,
width: props.width,
height: props.height,
ref: canvasEl
})
])
}
}
}
})

export const Bar = /* #__PURE__ */ generateChart(
'bar-chart',
4 changes: 0 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import mixins from './mixins/index.js'

import {
Bar,
Doughnut,
@@ -21,7 +19,6 @@ const VueCharts = {
Radar,
Bubble,
Scatter,
mixins,
generateChart,
render: () =>
console.error(
@@ -41,6 +38,5 @@ export {
Radar,
Bubble,
Scatter,
mixins,
generateChart
}
106 changes: 0 additions & 106 deletions src/mixins/index.js

This file was deleted.