Skip to content

Commit 6f8fa51

Browse files
authored
feat: add reactivity to options (#840)
1 parent 54fbdf6 commit 6f8fa51

File tree

5 files changed

+119
-229
lines changed

5 files changed

+119
-229
lines changed

README.md

Lines changed: 7 additions & 218 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,9 @@ Supports Chart.js v3 and v2.
2121
<br />
2222
<a href="#install">Install</a>
2323
<span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
24-
<a href="#docs">Docs</a>
25-
<span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
2624
<a href="#how-to-use">How to use</a>
2725
<span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
28-
<a href="#migration-to-v4">Migration to v4</a>
29-
<span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
30-
<a href="#demo">Demo</a>
26+
<a href="#docs">Docs</a>
3127
<span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
3228
<a href="https://slack.cube.dev/?ref=eco-vue-chartjs">Slack</a>
3329
<span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
@@ -57,10 +53,6 @@ Need an API to fetch data? Consider [Cube](https://cube.dev/?ref=eco-vue-chartjs
5753

5854
[![supported by Cube](https://user-images.githubusercontent.com/986756/154330861-d79ab8ec-aacb-4af8-9e17-1b28f1eccb01.svg)](https://cube.dev/?ref=eco-vue-chartjs)
5955

60-
## Docs
61-
62-
- 📖 [Docs](http://vue-chartjs.org/)
63-
6456
## How to use
6557

6658
This package works with version 2.x and 3.x of Vue.
@@ -228,216 +220,13 @@ export default {
228220
</script>
229221
```
230222

231-
## Reactivity
232-
233-
vue-chartjs will update or re-render the chart if new data is passed.
234-
235-
## Migration to v4
236-
237-
With v4, this library introduces a number of breaking changes. In order to improve performance, offer new features, and improve maintainability, it was necessary to break backwards compatibility, but we aimed to do so only when worth the benefit.
238-
239-
v4 is fully compatible with Chart.js v3.
240-
241-
### Tree-shaking
242-
243-
v4 of this library, [just like Chart.js v3](https://www.chartjs.org/docs/latest/getting-started/v3-migration.html#setup-and-installation), is tree-shakable. It means that you need to import and register the controllers, elements, scales, and plugins you want to use.
244-
245-
For a list of all the available items to import, see [Chart.js docs](https://www.chartjs.org/docs/latest/getting-started/integration.html#bundlers-webpack-rollup-etc).
246-
247-
v3:
248-
249-
```javascript
250-
import { Bar } from 'vue-chartjs'
251-
```
252-
253-
v4 — lazy way:
254-
255-
```javascript
256-
import 'chart.js/auto';
257-
import { Bar } from 'vue-chartjs'
258-
```
259-
260-
v4 — tree-shakable way:
261-
262-
```javascript
263-
import { Bar } from 'vue-chartjs'
264-
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'
265-
266-
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
267-
```
268-
269-
Using the "lazy way" is okay to simplify the migration, but please consider using the tree-shakable way to decrease the bundle size.
270-
271-
Please note that typed chart components register their controllers by default, so you don't need to register them by yourself. For example, when using the Pie component, you don't need to register PieController explicitly.
272-
273-
```javascript
274-
import { Pie } from 'vue-chartjs'
275-
import { Chart as ChartJS, Title, Tooltip, Legend, ArcElement, CategoryScale } from 'chart.js'
276-
277-
ChartJS.register(Title, Tooltip, Legend, ArcElement, CategoryScale)
278-
```
279-
280-
### Changing the creation of Charts
281-
282-
In v3, you needed to import the component, and then either use extends or mixins and add it.
283-
284-
v3:
285-
286-
```javascript
287-
// BarChart.js
288-
import { Bar } from 'vue-chartjs'
289-
290-
export default {
291-
extends: Bar,
292-
mounted () {
293-
// Overwriting base render method with actual data.
294-
this.renderChart({
295-
labels: ['January', 'February', 'March'],
296-
datasets: [
297-
{
298-
label: 'GitHub Commits',
299-
backgroundColor: '#f87979',
300-
data: [40, 20, 12]
301-
}
302-
]
303-
})
304-
}
305-
}
306-
```
307-
308-
```vue
309-
<template>
310-
<BarChart />
311-
</template>
312-
313-
<script>
314-
// DataPage.vue
315-
import BarChart from 'path/to/component/BarChart'
316-
317-
export default {
318-
name: 'DataPage',
319-
components: { BarChart }
320-
}
321-
</script>
322-
```
323-
324-
In v4, you need to import the component, pass props to it, and use Chart component as a standard Vue component.
325-
326-
```vue
327-
<template>
328-
<Bar :chart-data="chartData" />
329-
</template>
330-
331-
<script>
332-
// DataPage.vue
333-
import { Bar } from 'vue-chartjs'
334-
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'
335-
336-
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
337-
338-
export default {
339-
name: 'BarChart',
340-
components: { Bar },
341-
data() {
342-
return {
343-
chartData: {
344-
labels: [ 'January', 'February', 'March'],
345-
datasets: [
346-
{
347-
label: 'Data One',
348-
backgroundColor: '#f87979',
349-
data: [40, 20, 12]
350-
}
351-
]
352-
}
353-
}
354-
}
355-
}
356-
</script>
357-
```
358-
359-
### New reactivity system
360-
361-
v3 does not update or re-render the chart if new data is passed. You needed to use `reactiveProp` and `reactiveData` mixins for that.
362-
363-
v3:
364-
365-
```javascript
366-
import { Line, mixins } from 'vue-chartjs'
367-
368-
export default {
369-
extends: Line,
370-
mixins: [mixins.reactiveProp],
371-
props: ['chartData', 'options'],
372-
mounted () {
373-
this.renderChart(this.chartData, this.options)
374-
}
375-
}
376-
```
377-
378-
v4 charts have data change watcher by default. v4 will update or re-render the chart if new data is passed. Mixins have been removed.
379-
380-
v4:
381-
382-
```vue
383-
<template>
384-
<Bar :chart-data="chartData" />
385-
</template>
386-
387-
<script>
388-
// DataPage.vue
389-
import { Bar } from 'vue-chartjs'
390-
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'
391-
392-
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
393-
394-
export default {
395-
name: 'BarChart',
396-
components: { Bar },
397-
computed: {
398-
chartData() { return /* mutable chart data */ }
399-
}
400-
}
401-
</script>
402-
```
403-
404-
## Demo
405-
406-
- 📺 [Demo](http://demo.vue-chartjs.org/)
407-
408-
## Available Charts
409-
410-
### Bar Chart
411-
412-
![Bar](assets/bar.png)
413-
414-
### Line Chart
415-
416-
![Line](assets/line.png)
417-
418-
### Doughnut
419-
420-
![Doughnut](assets/doughnut.png)
421-
422-
### Pie
423-
424-
![Pie](assets/pie.png)
425-
426-
### Radar
427-
428-
![Pie](assets/radar.png)
429-
430-
### Polar Area
431-
432-
![Pie](assets/polar.png)
433-
434-
### Bubble
435-
436-
![Bubble](assets/bubble.png)
437-
438-
### Scatter
223+
## Docs
439224

440-
![Scatter](assets/scatter.png)
225+
- [Reactivity](https://vue-chartjs.org/guide/#updating-charts)
226+
- [Access to Chart instance](https://vue-chartjs.org/guide/#access-to-chart-instance)
227+
- [Migration to v4](https://vue-chartjs.org/migration-to-v4/)
228+
- [API](https://vue-chartjs.org/api/)
229+
- [Examples](https://vue-chartjs.org/examples/)
441230

442231
## Build Setup
443232

legacy/src/Charts.js

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ import {
1919
setChartDatasets,
2020
compareData,
2121
templateError,
22-
ChartEmits
22+
ChartEmits,
23+
setChartOptions
2324
} from '../../src/utils'
2425

2526
const ANNOTATION_PLUGIN_KEY = 'annotation'
@@ -91,8 +92,17 @@ export function generateChart(chartId, chartType, chartController) {
9192
}
9293
},
9394
watch: {
94-
chartData(newValue, oldValue) {
95-
this.chartDataHandler(newValue, oldValue)
95+
chartData: {
96+
handler: function (newValue, oldValue) {
97+
this.chartDataHandler(newValue, oldValue)
98+
},
99+
deep: true
100+
},
101+
chartOptions: {
102+
handler: function (newValue) {
103+
this.chartOptionsHandler(newValue)
104+
},
105+
deep: true
96106
}
97107
},
98108
methods: {
@@ -139,7 +149,7 @@ export function generateChart(chartId, chartType, chartController) {
139149
this.$emit(ChartEmits.LabelsUpdated)
140150
}
141151

142-
chartUpdate(currentChart)
152+
this.updateChart()
143153
this.$emit(ChartEmits.ChartUpdated)
144154
} else {
145155
if (currentChart !== null) {
@@ -160,6 +170,20 @@ export function generateChart(chartId, chartType, chartController) {
160170
this.$emit(ChartEmits.ChartRendered)
161171
}
162172
},
173+
chartOptionsHandler(options) {
174+
const currentChart = this.getCurrentChart()
175+
176+
if (currentChart !== null) {
177+
setChartOptions(currentChart, options)
178+
this.updateChart()
179+
} else {
180+
chartCreate(this.renderChart, this.chartData, this.chartOptions)
181+
}
182+
},
183+
updateChart() {
184+
const currentChart = this.getCurrentChart()
185+
chartUpdate(currentChart)
186+
},
163187
getCurrentChart() {
164188
return this.hasAnnotationPlugin ? _chartRef.current : this.$data._chart
165189
},

src/BaseCharts.ts

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ import {
3939
setChartLabels,
4040
setChartDatasets,
4141
compareData,
42-
templateError
42+
templateError,
43+
chartUpdateError,
44+
setChartOptions
4345
} from './utils'
4446

4547
import type {
@@ -165,7 +167,7 @@ export const generateChart = <
165167
)
166168
}
167169

168-
chartUpdate<TType, TData, TLabel>(chart, context)
170+
updateChart()
169171
} else {
170172
if (chart !== null) {
171173
chartDestroy<TType, TData, TLabel>(chart, context)
@@ -192,6 +194,32 @@ export const generateChart = <
192194
}
193195
}
194196

197+
function chartOptionsHandler(options: TChartOptions<TType>): void {
198+
const chart = toRaw(_chart.value)
199+
200+
if (chart !== null) {
201+
setChartOptions<TType, TData, TLabel>(chart, options)
202+
updateChart()
203+
} else {
204+
chartCreate<TType, TData, TLabel>(
205+
renderChart,
206+
props.chartData,
207+
props.chartOptions as ChartOptions<TType>,
208+
context
209+
)
210+
}
211+
}
212+
213+
function updateChart(): void {
214+
const chart = toRaw(_chart.value)
215+
216+
if (chart !== null) {
217+
chartUpdate<TType, TData, TLabel>(chart, context)
218+
} else {
219+
console.error(chartUpdateError)
220+
}
221+
}
222+
195223
watch(
196224
() => props.chartData,
197225
(
@@ -201,6 +229,12 @@ export const generateChart = <
201229
{ deep: true }
202230
)
203231

232+
watch(
233+
() => props.chartOptions,
234+
newValue => chartOptionsHandler(newValue as ChartOptions<TType>),
235+
{ deep: true }
236+
)
237+
204238
onMounted(() => {
205239
if (
206240
'datasets' in props.chartData &&
@@ -221,6 +255,11 @@ export const generateChart = <
221255
}
222256
})
223257

258+
context.expose({
259+
chart: _chart,
260+
updateChart
261+
})
262+
224263
return () =>
225264
h('div', { style: props.styles, class: props.cssClasses }, [
226265
h('canvas', {

0 commit comments

Comments
 (0)