docs/pt-br/guide/README.md
# Começando
**vue-chartjs** é um pacote para [Chart.js](https://github.com/chartjs/Chart.js) no Vue. Com ele você pode criar facilmente componentes de gráficos reutilizáveis.
## Introdução
`vue-chartjs` permite você usar Chart.js sem muito aborrecimento dentro do Vue. É perfeito para pessoas que precisam de gráficos simples em funcionamento o mais rápido possível.
Abstrai a lógica básica, mas expõe o objeto Chart.js para oferecer a máxima flexibilidade.
## Instalação
### NPM
Você pode instalar o `vue-chartjs` através do `npm` ou `yarn`. No entanto, você também precisa adicionar o `chart.js` como uma dependência ao seu projeto, porque o `Chart.js` é um parDeDependência. Dessa forma, você tem total controle sobre o versionamento do `Chart.js`.
```bash
npm install vue-chartjs chart.js --save
```
```bash
yarn add vue-chartjs chart.js
```
::: tip Dica
Se você estiver utilizando vue 1.x por favor use a tag `legacy`. No entanto, a versão 1 do Vue não é mais mantida.
`yarn add vue-chartjs@legacy`
:::
### Navegador
Você também pode usar `vue-chartjs` diretamente no navegador via CDN.
Primeiro, adicione o script do `Chart.js`, e depois adicione o script `vue-chartjs`.
```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js"></script>
<script src="https://unpkg.com/vue-chartjs/dist/vue-chartjs.min.js"></script>
```
## Integração
Todo tipo de gráfico disponível em `Chart.js` é exportado como um componente nomeado e pode ser importado como tal. Esses componentes são componentes normais do Vue, no entanto, você precisa estendê-lo com `extend`.
A ideia por trás do `vue-chartjs` é fornecer componentes fáceis de usar, com máxima flexibilidade e extensibilidade. Para alcançar isto, você precisa criar o seu próprio _Componente de gráfico_ e estendê-lo com os componentes `vue-chartjs` fornecidos.
Dessa forma, os métodos e a lógica nos componentes do gráfico são mesclados no seu próprio componente de gráfico.
## Criando seu primeiro Gráfico
primeiro, você precisa importar o gráfico base e estendê-lo. Isso oferece mais flexibilidade ao trabalhar com dados diferentes. Você pode encapsular seus componentes e usar objetos para passar dados, ou você pode inseri-los diretamente dentro do componente. No entanto, seu componente não é reutilizável dessa maneira.
Você pode importar o pacote inteiro ou cada módulo individualmente. Então, você precisa usar `extends:` ou `mixins:[]`. Depois, no gancho `mounted()`, chame `this.renderChart()`. Isso criará sua instância do gráfico.
```js{1,4,6}
import { Bar } from "vue-chartjs";
export default {
extends: Bar,
mounted() {
this.renderChart(data, options);
}
};
```
:::tip Dica
Você pode usar `extends: Bar` ou `mixins: [Bar]`
:::
O método `this.renderChart()` é fornecido pelo componente `Bar` e aceita dois parâmetros: ambos são `objetos`. O primeiro são os dados do gráfico, e o segundo é um objeto de opções.
Confira o oficial [Chart.js docs](http://www.chartjs.org/docs/latest/#creating-a-chart) para ver a estrutura do objeto que você precisa fornecer.
### Componentes de arquivo único do Vue
A maioria dos exemplos nos documentos é baseada em arquivos JavaScript e não em arquivos `.vue`. Isso ocorre porque, principalmente, você precisará apenas do bloco `<script>`. No entanto, você também pode usar componentes single-file `.vue`.
**Chart.vue**
```js
<script>
import { Line } from 'vue-chartjs'
export default {
extends: Line,
props: ['chartdata', 'options'],
mounted () {
this.renderChart(this.chartdata, this.options)
}
}
</script>
<style>
</style>
```
::: danger A tag template não pode ser mesclada
Não inclua a tag `<template>` em seus componentes single-file `.vue`. Vue pode **não** mesclar templates. Se você adicionar uma tag `<template>` vazia, o Vue pegará o modelo do seu componente e não do estendido, o que resultará em um template vazio e erros inesperados.
:::
## Atualizando Gráficos
`Chart.js` não fornece uma atualização ao vivo se você alterar os conjuntos de dados. No entanto, `vue-chartjs` fornece dois mixins para atingir esse objetivo:
- `reactiveProp`
- `reactiveData`
Ambos os mixins alcançam o mesmo resultado. Na maioria das vezes você usará `reactiveProp`. Ele estende a lógica do seu componente de gráfico e cria automaticamente um objeto chamado `chartData` e adiciona um `vue watch` neste objeto. Na mutação de dados, ele chamará `update()` se os dados dentro dos conjuntos de dados foram alterados, ou `renderChart()` se novos conjuntos de dados foram adicionados.
`reactiveData` simplesmente cria uma variável local `chartData` (o que não é um `objeto`!) e adiciona um observador. Isso é útil apenas se você precisar de gráficos de finalidade única ou precisar de uma chamada de API dentro do componente do gráfico.
### Exemplo
**LineChart.js**
```js
import { Line, mixins } from "vue-chartjs";
const { reactiveProp } = mixins;
export default {
extends: Line,
mixins: [reactiveProp],
props: ["options"],
mounted() {
// this.chartData é criado no mixin.
// Se você deseja passar opções, crie um objeto de opções locais
this.renderChart(this.chartData, this.options);
}
};
```
**RandomChart.vue**
```vue
<template>
<div class="small">
<line-chart :chart-data="datacollection"></line-chart>
<button @click="fillData()">Randomize</button>
</div>
</template>
<script>
import LineChart from "./LineChart.js";
export default {
components: {
LineChart
},
data() {
return {
datacollection: null
};
},
mounted() {
this.fillData();
},
methods: {
fillData() {
this.datacollection = {
labels: [this.getRandomInt(), this.getRandomInt()],
datasets: [
{
label: "Data One",
backgroundColor: "#f87979",
data: [this.getRandomInt(), this.getRandomInt()]
},
{
label: "Data One",
backgroundColor: "#f87979",
data: [this.getRandomInt(), this.getRandomInt()]
}
]
};
},
getRandomInt() {
return Math.floor(Math.random() * (50 - 5 + 1)) + 5;
}
}
};
</script>
<style>
.small {
max-width: 600px;
margin: 150px auto;
}
</style>
```
::: danger Limitações
[Caveats](https://vuejs.org/v2/guide/list.html#Caveats)
[Change-Detection-Caveats](https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats)
[vm.\$watch](https://vuejs.org/v2/api/#vm-watch)
:::
### Eventos
Esses mixins reativos emitem eventos se os dados forem alterados. Você pode ouvi-los com `v:on` no componente do gráfico. Os seguintes eventos estão disponíveis:
- `chart:render` - se o mixin executar um renderizador completo
- `chart:destroy` - se o mixin excluir a instância do objeto de gráfico
- `chart:update` - se o mixin executar uma atualização em vez de uma nova renderização
- `labels:update` - se novos labels foram definidos
- `xlabels:update` se novos xLabels foram definidos
- `ylabels:update` - se novos yLabels foram definidos
### Solução de problemas
O sistema de reatividade em seu estado atual não é **robusto**. Você terá vários problemas com isso, porque existem muitos casos de uso e maneiras de passar seus dados.
#### Opções
O objeto `options` não está atualmente implementado reativamente. Portanto, se você alterar dinamicamente as opções do gráfico, eles não serão reconhecidos pelo mixin. Se necessário, você pode criar um observador para destruir e renderizar novamente quando as opções do gráfico forem atualizadas.
Se você estiver usando o mixin, precisará passar suas opções como um objeto chamado `options`. Isso é importante porque o mixin chamará o método `update ()` do Chart.js ou destruirá e renderizará um novo gráfico. Se o mixin renderizar um novo gráfico, ele chamará `this.renderChart(this.chartData, this.options)`.
Mas, se você passar suas opções diretamente no seu gancho `mounted()`, elas serão destruídas.
::: danger Maneira errada
```js{7}
import { Line, mixins } from 'vue-chartjs'
export default {
components: { Line }
mixins: [mixins.reactiveProp],
mounted () {
this.renderChart(this.chartData, {responsive: true})
}
}
```
:::
::: tip Maneira Certo
```js{7}
import { Line, mixins } from 'vue-chartjs'
export default {
components: { Line }
mixins: [mixins.reactiveProp],
mounted () {
this.renderChart(this.chartData, this.options)
}
}
```
:::
#### Próprio observador
Se você transformar seus dados, mutação (em vez de enviar novos dados), é o melhor método, se você implementar seu próprio observador.
Você pode chamar `this.$data._chart.update()` ou `this.renderChart()` de forma independente, dependendo de suas necessidades.
Um observador simples seria:
```js
watch: {
chartData () {
this.$data._chart.update()
}
}
```
## Exemplos
### Gráfico com props
Seu objetivo deve ser criar componentes reutilizáveis do gráfico. Para esse fim, você deve utilizar as `props` do Vue.js para passar suas opções e seus dados do gráfico. Dessa forma, o próprio gráfico não possui uma opinião sobre a busca de dados e é apenas para apresentação.
Primeiro, crie seu componente:
```js
import { Line } from "vue-chartjs";
export default {
extends: Line,
props: {
chartdata: {
type: Object,
default: null
},
options: {
type: Object,
default: null
}
},
mounted() {
this.renderChart(this.chartdata, this.options);
}
};
```
Depois disso, você pode adicionar o componente do gráfico a um componente pai:
```vue
<line-chart :chartdata="chartData" :options="chartOptions" />
```
### Gráfico com dados locais
Você pode manipular os dados do gráfico diretamente em seu próprio componente do gráfico. Você só precisa passá-lo para o método `renderChart()`:
```js
import { Bar } from "vue-chartjs";
export default {
extends: Bar,
data: () => ({
chartdata: {
labels: ["January", "February"],
datasets: [
{
label: "Data One",
backgroundColor: "#f87979",
data: [40, 20]
}
]
},
options: {
responsive: true,
maintainAspectRatio: false
}
}),
mounted() {
this.renderChart(this.chartdata, this.options);
}
};
```
### Gráfico com dados da API
Um padrão comum é usar uma API para recuperar seus dados. No entanto, existem algumas coisas para ter em mente. O problema mais comum é que você monta o componente do gráfico diretamente e transmite dados de uma chamada de API assíncrona. O problema dessa abordagem é que o Chart.js tenta renderizar seu gráfico e acessar os dados do gráfico de forma sincronizada, para que o gráfico seja montado antes que os dados da API cheguem.
Para evitar isso, um simples `v-if` é a melhor solução.
Crie seu componente de gráfico com um objeto de dados e opções, para que possamos transmitir nossos dados e opções de um componente de contêiner.
**Chart.vue**
```js
import { Line } from "vue-chartjs";
export default {
extends: Line,
props: {
chartdata: {
type: Object,
default: null
},
options: {
type: Object,
default: null
}
},
mounted() {
this.renderChart(this.chartdata, this.options);
}
};
```
Em seguida, crie um componente de contêiner, que lida com a chamada da API ou a conexão vuex.
**ChartContainer.vue**
```html {3}
<template>
<div class="container">
<line-chart v-if="loaded" :chartdata="chartdata" :options="options" />
</div>
</template>
<script>
import LineChart from "./Chart.vue";
export default {
name: "LineChartContainer",
components: { LineChart },
data: () => ({
loaded: false,
chartdata: null
}),
async mounted() {
this.loaded = false;
try {
const { userlist } = await fetch("/api/userlist");
this.chartdata = userlist;
this.loaded = true;
} catch (e) {
console.error(e);
}
}
};
</script>
```
### Gráfico com estilos dinâmicos
Você pode definir `responsive: true` e passar um objeto de estilos que é aplicado como estilos embutidos para o exterior `<div>`. Dessa forma, você pode alterar a altura e a largura do contêiner externo dinamicamente, o que não é o comportamento padrão do Chart.js. É melhor usar propriedades computadas para isso.
::: warning Aviso
Você precisa definir `position: relative`
:::
```html
<template>
<div>
<line-chart :styles="myStyles" />
<button @click="increase()">Increase height</button>
</div>
</template>
<script>
export default {
data() {
return {
height: 300
};
},
methods: {
increase() {
this.height += 10;
}
},
computed: {
myStyles() {
return {
height: `${this.height}px`,
position: "relative"
};
}
}
};
</script>
```
### Personalizados / Novos Gráficos
Às vezes, você precisa estender os gráficos Chart.js padrão. Existem muitos [exemplos](http://www.chartjs.org/docs/latest/developers/charts.html) sobre como estender e modificar os gráficos padrão. Ou você pode criar seu próprio tipo de gráfico.
No `vue-chartjs`, você pode fazer isso da mesma maneira:
```js
// 1. Importar Chart.js para que você possa usar o objeto Chart global
import Chart from "chart.js";
// 2. Importar o metodo `generateChart()` para criar o componente vue.
import { generateChart } from "vue-chartjs";
// 3. Estenda um dos gráficos padrão
// http://www.chartjs.org/docs/latest/developers/charts.html
Chart.defaults.LineWithLine = Chart.defaults.line;
Chart.controllers.LineWithLine = Chart.controllers.line.extend({
/* personalize sua magica aqui */
});
// 4. Gere o componente vue-chartjs
// O primeiro argumento é o ID do gráfico, depois o tipo de gráfico.
const CustomLine = generateChart("custom-line", "LineWithLine");
// 5. Estender o component CustomLine assim como você faz com os gráficos vue-chartjs padrão.
export default {
extends: CustomLine,
mounted() {
// ....
}
};
```
## Recursos
Aqui estão alguns recursos, como tutoriais, sobre como usar `vue-chartjs`:
- [Usando vue-chartjs com WordPress](https://medium.com/@apertureless/wordpress-vue-and-chart-js-6b61493e289f)
- [Crie gráficos impressionantes com Vue e Chart.js](https://hackernoon.com/creating-stunning-charts-with-vue-js-and-chart-js-28af584adc0a)
- [Vamos construir um aplicativo web com Vue, Chart.js e uma API Parte I](https://hackernoon.com/lets-build-a-web-app-with-vue-chart-js-and-an-api-544eb81c4b44)
- [Vamos construir um aplicativo web com Vue, Chart.js e uma API Parte II](https://hackernoon.com/lets-build-a-web-app-with-vue-chart-js-and-an-api-part-ii-39781b1d5acf)
- [Construir um gráfico em tempo real com VueJS e Pusher](https://blog.pusher.com/build-realtime-chart-with-vuejs-pusher/)