symfony/ux-chartjs
Symfony UX Chart.js is a Symfony bundle that integrates Chart.js into Symfony apps. Part of the Symfony UX initiative, it helps you build and render interactive charts with modern UX tooling. Documentation and issues are managed in the main symfony/ux repo.
composer require symfony/ux-chartjs
config/bundles.php:
return [
// ...
Symfony\UX\ChartJsBundle\ChartJsBundle::class => ['all' => true],
];
composer require chartjs/chart.js
{% use 'chartjs_chart.html.twig' %}
{{ component('chartjs_chart', {
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar'],
datasets: [{
label: 'Sales',
data: [10, 20, 30]
}]
}
}) }}
// src/Controller/ChartController.php
public function dashboard(ChartController $controller): Response
{
return $this->render('dashboard.html.twig', [
'chartData' => $controller->getSalesData(),
]);
}
{{ component('chartjs_chart', {
type: 'bar',
data: chartData,
options: { responsive: true }
}) }}
Data Binding:
{{ component('live_chart', {
data: controller.fetchLiveData()
}) }}
{{ component('chartjs_chart', {
data: controller.apiFetch('metrics')
}) }}
Chart Customization:
options key (Chart.js config).
options: {
plugins: { title: { display: true, text: 'Monthly Sales' } },
scales: { y: { beginAtZero: true } }
}
assets/app.js:
import { Chart } from 'chart.js';
import annotationPlugin from 'chartjs-plugin-annotation';
Chart.register(annotationPlugin);
Live Updates:
// assets/controllers/chart_controller.js
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
connect() {
this.chart = this.element.chart;
}
updateData(data) {
this.chart.data = data;
this.chart.update();
}
}
{{ component('chartjs_chart', {
data: chartData,
stimulus: 'chart'
}) }}
Reusable Components:
{# templates/components/chart/line.html.twig #}
{% extends 'chartjs_chart.html.twig' %}
{% block type %}line{% endblock %}
// src/Components/ChartComponent.php
public function getSalesData(): array
{
return $this->getSalesRepository()->findMonthlySales();
}
chart.js is in package.json and resolved in webpack.config.js.vite.config.js:
optimizeDeps: {
include: ['chart.js', 'chartjs-plugin-datalabels']
}
use statements for components (not component() helper).LiveComponent for real-time updates:
{{ component('live_chart', {
data: controller.streamData()
}) }}
{{ dump(component('chartjs_chart')) }} to inspect component state.Symfony 7.x Migration:
use statements, not component() helper.
{# ❌ Old #}
{{ component('chartjs_chart', {}) }}
{# ✅ New #}
{% use 'chartjs_chart.html.twig' %}
chart.js is optimized.
// vite.config.js
optimizeDeps: {
include: ['chart.js']
}
Chart.js Version Conflicts:
Chart.register() (no chartjs/auto).
// assets/app.js
import { Chart } from 'chart.js';
import { LineController } from 'chartjs-chart-line';
Chart.register(LineController);
chartjs-plugin-datalabels@2.x).LiveComponent Quirks:
data-symfony--ux-chartjs--chart-view-value updates trigger re-renders.chartjs:connect and chartjs:view-value-change for custom logic.
this.element.addEventListener('chartjs:view-value-change', (e) => {
console.log('Data updated:', e.detail);
});
Asset Loading:
chart.js is in package.json and built.
npm install chart.js
npm run build
vite.config.js for missing dependencies.assets/app.js:
import { Application } from '@hotwired/stimulus';
const application = Application.start();
application.debug = true; // Logs all Stimulus actions
Chart is not defined errors (missing chart.js import).console.log(this.chart) in Stimulus controllers to inspect instances.{{ dump(component('chartjs_chart')) }}
Custom Chart Types:
ChartJsController for reusable logic:
// src/Controller/CustomChartController.php
public function getBarChartData(): array
{
return ['labels' => [...], 'datasets' => [...]];
}
{{ component('custom_chart', {}) }}
Stimulus Extensions:
chart_controller.js:
updateData(data) {
this.chart.data = data;
this.chart.update();
this.dispatch('chart-updated', { detail: data });
}
<button data-action="click->chart#updateData">Refresh</button>
Mercure Integration:
{{ component('live_chart', {
mercureUpdate: controller.getMercureUpdate()
}) }}
connect() {
this.subscription = Mercure.subscribe(this.data.get('mercureUpdate'), (event) => {
this.updateData(JSON.parse(event.data));
});
}
assets/src (not Resources/assets/).package.json scripts if needed:
"scripts": {
"build": "vite build assets/src --base /"
}
ChartJsController methods:
$this->render('chart.html.twig', [
'chartData' => $this->getChartData(type: 'line'),
]);
framework.asset_mapper in config/packages/framework.yaml:
framework:
asset_mapper: true
How can I help you explore Laravel packages today?