Data

Chart

Wrapper Vue 3 per Chart.js che supporta grafici bar, line, pie, doughnut, radar, polarArea, bubble e scatter con aggiornamento reattivo.

Dipendenze

Il componente richiede chart.js come peer dependency:

npm install chart.js

Import

import { Chart } from '@pzeta/vue-components'

Esempio Base

Props

PropTipoDefaultDescrizione
typeChartType'bar'Tipo di grafico da visualizzare
dataChartData—Dati del grafico in formato Chart.js
optionsChartOptions—Opzioni di configurazione Chart.js
pluginsPlugin[]—Plugin Chart.js personalizzati
localestring'it-IT'Locale di Intl.NumberFormat per i valori sugli assi e nel tooltip (vedi Formattazione dei valori)
widthnumber300Larghezza del canvas in px (modalita' non responsive)
heightnumber150Altezza del canvas in px (modalita' non responsive)
classstring—Classe CSS aggiuntiva per il container

ChartType

Valori accettati per la prop type:

ValoreDescrizione
'bar'Grafico a barre
'line'Grafico a linee
'pie'Grafico a torta
'doughnut'Grafico a ciambella
'radar'Grafico radar
'polarArea'Grafico ad area polare
'bubble'Grafico a bolle
'scatter'Grafico a dispersione

Emits

EventoPayloadDescrizione
chartCreateChartInstanceEmesso quando l'istanza Chart.js viene creata
chartUpdateChartInstanceEmesso quando il grafico viene aggiornato con nuovi dati
chartDestroy—Emesso quando l'istanza Chart.js viene distrutta

Metodi Esposti (defineExpose)

Il componente espone i seguenti metodi tramite ref:

Metodo/Proprieta'TipoDescrizione
chartChartInstance | nullRiferimento reattivo all'istanza Chart.js corrente
refresh()() => voidAggiorna il grafico con i dati correnti (senza ricreare l'istanza)
reinit()() => voidReinizializza completamente il grafico (utile al cambio di type)
getChart()() => ChartInstance | nullRestituisce l'istanza Chart.js corrente

Esempi

Grafico a Linee

<script setup lang="ts">
import type { ChartData, ChartOptions } from 'chart.js'

const lineData: ChartData = {
  labels: ['Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab', 'Dom'],
  datasets: [
    {
      label: 'Visitatori',
      data: [120, 190, 300, 250, 220, 310, 180],
      fill: true,
      backgroundColor: 'rgba(34, 197, 94, 0.2)',
      borderColor: 'rgb(34, 197, 94)',
      tension: 0.4,
    },
  ],
}

const lineOptions: ChartOptions = {
  responsive: true,
  plugins: {
    legend: { position: 'top' },
    title: { display: true, text: 'Visitatori della settimana' },
  },
}
</script>

<template>
  <Chart type="line" :data="lineData" :options="lineOptions" />
</template>

Grafico a Torta

<script setup lang="ts">
import type { ChartData } from 'chart.js'

const pieData: ChartData = {
  labels: ['Rosso', 'Blu', 'Verde', 'Giallo'],
  datasets: [
    {
      data: [300, 50, 100, 80],
      backgroundColor: [
        'rgb(239, 68, 68)',
        'rgb(59, 130, 246)',
        'rgb(34, 197, 94)',
        'rgb(245, 158, 11)',
      ],
    },
  ],
}
</script>

<template>
  <Chart type="pie" :data="pieData" />
</template>

Grafico Radar

<script setup lang="ts">
import type { ChartData } from 'chart.js'

const radarData: ChartData = {
  labels: ['Velocita', 'Affidabilita', 'Comfort', 'Sicurezza', 'Efficienza'],
  datasets: [
    {
      label: 'Prodotto A',
      data: [65, 75, 70, 80, 60],
      backgroundColor: 'rgba(59, 130, 246, 0.2)',
      borderColor: 'rgb(59, 130, 246)',
    },
    {
      label: 'Prodotto B',
      data: [55, 85, 65, 90, 75],
      backgroundColor: 'rgba(34, 197, 94, 0.2)',
      borderColor: 'rgb(34, 197, 94)',
    },
  ],
}
</script>

<template>
  <Chart type="radar" :data="radarData" />
</template>

Aggiornamento Programmatico

<script setup lang="ts">
import { ref } from 'vue'
import type { ChartData } from 'chart.js'

const chartRef = ref()
const chartData = ref<ChartData>({
  labels: ['A', 'B', 'C'],
  datasets: [{ label: 'Dati', data: [10, 20, 30], backgroundColor: 'rgba(59, 130, 246, 0.5)' }],
})

function aggiornaGrafico() {
  chartData.value.datasets[0].data = [Math.random() * 100, Math.random() * 100, Math.random() * 100]
  chartRef.value?.refresh()
}
</script>

<template>
  <Chart ref="chartRef" type="bar" :data="chartData" />
  <button @click="aggiornaGrafico">Aggiorna dati</button>
</template>

Formattazione dei valori

I valori sugli assi e nel tooltip sono formattati con locale (default it-IT). La formattazione va sull'asse dei valori: y di default, x nelle barre orizzontali (options.indexAxis: 'y'), entrambi in scatter e bubble. L'asse delle categorie mostra data.labels. Un scales.<asse>.type dichiarato vince: category e time non vengono mai formattati come numeri, linear e logarithmic sempre. Un ticks.callback passato nelle options sostituisce quello della libreria.

Il tooltip mostra il solo valore (radar e polarArea: il valore sul raggio; scatter e bubble: la coppia (x, y)). Prima della 1.22.0 le barre orizzontali mostravano 0, 1, 2 sull'asse delle categorie e il tooltip dei grafici a barre e linee mostrava «(indice, valore)».

Note Comportamento

  • Il componente registra automaticamente tutti i controller e gli elementi Chart.js necessari
  • I colori del testo e della griglia vengono letti dalle variabili CSS --chart-text-color e --chart-grid-color per integrazione con il tema
  • Le opzioni passate via options vengono unite con le opzioni di default (deep merge); le opzioni fornite hanno precedenza
  • Il watch su data e options e' debounced a 100ms per evitare aggiornamenti eccessivi
  • Al cambio di type, il grafico viene completamente reinizializzato
  • Usa shallowRef internamente per evitare che Chart.js diventi reattivo in profondita', prevenendo problemi di performance

Costanti di Utilita'

Il modulo esporta costanti per colori predefiniti:

import { CHART_COLORS, CHART_PALETTE } from '@pzeta/vue-components'

// Colori singoli
CHART_COLORS.primary       // 'rgb(59, 130, 246)'
CHART_COLORS.success       // 'rgb(34, 197, 94)'
CHART_COLORS.danger        // 'rgb(239, 68, 68)'

// Palette per dataset multipli (8 colori)
CHART_PALETTE              // string[]

TypeScript

import type { ChartProps, ChartEmits, ChartExpose, ChartType } from '@pzeta/vue-components'
import type { ChartData, ChartOptions } from 'chart.js'

const chartData: ChartData = {
  labels: ['A', 'B', 'C'],
  datasets: [
    {
      label: 'Dataset',
      data: [10, 20, 30],
      backgroundColor: 'rgba(59, 130, 246, 0.5)',
    },
  ],
}