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

Add reactivity to options #840

Merged
merged 3 commits into from
May 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
225 changes: 7 additions & 218 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,9 @@ Supports Chart.js v3 and v2.
<br />
<a href="#install">Install</a>
<span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
<a href="#docs">Docs</a>
<span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
<a href="#how-to-use">How to use</a>
<span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
<a href="#migration-to-v4">Migration to v4</a>
<span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
<a href="#demo">Demo</a>
<a href="#docs">Docs</a>
<span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
<a href="https://slack.cube.dev/?ref=eco-vue-chartjs">Slack</a>
<span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
Expand Down Expand Up @@ -57,10 +53,6 @@ Need an API to fetch data? Consider [Cube](https://cube.dev/?ref=eco-vue-chartjs

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

## Docs

- 📖 [Docs](http://vue-chartjs.org/)

## How to use

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

## Reactivity

vue-chartjs will update or re-render the chart if new data is passed.

## Migration to v4

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.

v4 is fully compatible with Chart.js v3.

### Tree-shaking

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.

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).

v3:

```javascript
import { Bar } from 'vue-chartjs'
```

v4 — lazy way:

```javascript
import 'chart.js/auto';
import { Bar } from 'vue-chartjs'
```

v4 — tree-shakable way:

```javascript
import { Bar } from 'vue-chartjs'
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'

ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
```

Using the "lazy way" is okay to simplify the migration, but please consider using the tree-shakable way to decrease the bundle size.

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.

```javascript
import { Pie } from 'vue-chartjs'
import { Chart as ChartJS, Title, Tooltip, Legend, ArcElement, CategoryScale } from 'chart.js'

ChartJS.register(Title, Tooltip, Legend, ArcElement, CategoryScale)
```

### Changing the creation of Charts

In v3, you needed to import the component, and then either use extends or mixins and add it.

v3:

```javascript
// BarChart.js
import { Bar } from 'vue-chartjs'

export default {
extends: Bar,
mounted () {
// Overwriting base render method with actual data.
this.renderChart({
labels: ['January', 'February', 'March'],
datasets: [
{
label: 'GitHub Commits',
backgroundColor: '#f87979',
data: [40, 20, 12]
}
]
})
}
}
```

```vue
<template>
<BarChart />
</template>

<script>
// DataPage.vue
import BarChart from 'path/to/component/BarChart'

export default {
name: 'DataPage',
components: { BarChart }
}
</script>
```

In v4, you need to import the component, pass props to it, and use Chart component as a standard Vue component.

```vue
<template>
<Bar :chart-data="chartData" />
</template>

<script>
// DataPage.vue
import { Bar } from 'vue-chartjs'
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'

ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)

export default {
name: 'BarChart',
components: { Bar },
data() {
return {
chartData: {
labels: [ 'January', 'February', 'March'],
datasets: [
{
label: 'Data One',
backgroundColor: '#f87979',
data: [40, 20, 12]
}
]
}
}
}
}
</script>
```

### New reactivity system

v3 does not update or re-render the chart if new data is passed. You needed to use `reactiveProp` and `reactiveData` mixins for that.

v3:

```javascript
import { Line, mixins } from 'vue-chartjs'

export default {
extends: Line,
mixins: [mixins.reactiveProp],
props: ['chartData', 'options'],
mounted () {
this.renderChart(this.chartData, this.options)
}
}
```

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.

v4:

```vue
<template>
<Bar :chart-data="chartData" />
</template>

<script>
// DataPage.vue
import { Bar } from 'vue-chartjs'
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'

ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)

export default {
name: 'BarChart',
components: { Bar },
computed: {
chartData() { return /* mutable chart data */ }
}
}
</script>
```

## Demo

- 📺 [Demo](http://demo.vue-chartjs.org/)

## Available Charts

### Bar Chart

![Bar](assets/bar.png)

### Line Chart

![Line](assets/line.png)

### Doughnut

![Doughnut](assets/doughnut.png)

### Pie

![Pie](assets/pie.png)

### Radar

![Pie](assets/radar.png)

### Polar Area

![Pie](assets/polar.png)

### Bubble

![Bubble](assets/bubble.png)

### Scatter
## Docs

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

## Build Setup

Expand Down
32 changes: 28 additions & 4 deletions legacy/src/Charts.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import {
setChartDatasets,
compareData,
templateError,
ChartEmits
ChartEmits,
setChartOptions
} from '../../src/utils'

const ANNOTATION_PLUGIN_KEY = 'annotation'
Expand Down Expand Up @@ -91,8 +92,17 @@ export function generateChart(chartId, chartType, chartController) {
}
},
watch: {
chartData(newValue, oldValue) {
this.chartDataHandler(newValue, oldValue)
chartData: {
handler: function (newValue, oldValue) {
this.chartDataHandler(newValue, oldValue)
},
deep: true
},
chartOptions: {
handler: function (newValue) {
this.chartOptionsHandler(newValue)
},
deep: true
}
},
methods: {
Expand Down Expand Up @@ -139,7 +149,7 @@ export function generateChart(chartId, chartType, chartController) {
this.$emit(ChartEmits.LabelsUpdated)
}

chartUpdate(currentChart)
this.updateChart()
this.$emit(ChartEmits.ChartUpdated)
} else {
if (currentChart !== null) {
Expand All @@ -160,6 +170,20 @@ export function generateChart(chartId, chartType, chartController) {
this.$emit(ChartEmits.ChartRendered)
}
},
chartOptionsHandler(options) {
const currentChart = this.getCurrentChart()

if (currentChart !== null) {
setChartOptions(currentChart, options)
this.updateChart()
} else {
chartCreate(this.renderChart, this.chartData, this.chartOptions)
}
},
updateChart() {
const currentChart = this.getCurrentChart()
chartUpdate(currentChart)
},
getCurrentChart() {
return this.hasAnnotationPlugin ? _chartRef.current : this.$data._chart
},
Expand Down
43 changes: 41 additions & 2 deletions src/BaseCharts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ import {
setChartLabels,
setChartDatasets,
compareData,
templateError
templateError,
chartUpdateError,
setChartOptions
} from './utils'

import type {
Expand Down Expand Up @@ -165,7 +167,7 @@ export const generateChart = <
)
}

chartUpdate<TType, TData, TLabel>(chart, context)
updateChart()
} else {
if (chart !== null) {
chartDestroy<TType, TData, TLabel>(chart, context)
Expand All @@ -192,6 +194,32 @@ export const generateChart = <
}
}

function chartOptionsHandler(options: TChartOptions<TType>): void {
const chart = toRaw(_chart.value)

if (chart !== null) {
setChartOptions<TType, TData, TLabel>(chart, options)
updateChart()
} else {
chartCreate<TType, TData, TLabel>(
renderChart,
props.chartData,
props.chartOptions as ChartOptions<TType>,
context
)
}
}

function updateChart(): void {
const chart = toRaw(_chart.value)

if (chart !== null) {
chartUpdate<TType, TData, TLabel>(chart, context)
} else {
console.error(chartUpdateError)
}
}

watch(
() => props.chartData,
(
Expand All @@ -201,6 +229,12 @@ export const generateChart = <
{ deep: true }
)

watch(
() => props.chartOptions,
newValue => chartOptionsHandler(newValue as ChartOptions<TType>),
{ deep: true }
)

onMounted(() => {
if (
'datasets' in props.chartData &&
Expand All @@ -221,6 +255,11 @@ export const generateChart = <
}
})

context.expose({
chart: _chart,
updateChart
})

return () =>
h('div', { style: props.styles, class: props.cssClasses }, [
h('canvas', {
Expand Down
Loading