Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravelchartjs Laravel Package

fx3costa/laravelchartjs

Laravel ChartJS is a Laravel wrapper for Chart.js that lets you create interactive, responsive charts directly in PHP. It offers a simple API, Blade-friendly rendering, multiple chart types, and easy configuration for dashboards, reports, and data visualizations.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and wire it up

composer require fx3costa/laravelchartjs

On Laravel 5.5+ the ChartjsServiceProvider is auto-discovered. On older apps (or if discovery is disabled) register manually in config/app.php:

'providers' => [
    Fx3costa\LaravelChartjs\Providers\ChartjsServiceProvider::class,
],
'aliases' => [
    'Chartjs' => Fx3costa\LaravelChartjs\Facades\Chartjs::class,
],

Publish the config so you can see which Chart.js build is injected and how:

php artisan vendor:publish

First use case — one line chart in a dashboard

Build the chart in the controller (or a dedicated chart class), not in Blade:

use Chartjs;

public function index()
{
    $chart = Chartjs::name('signups')
        ->type('line')
        ->labels(['Jan', 'Feb', 'Mar', 'Apr'])
        ->datasets([
            [
                'label' => 'Signups',
                'data' => [12, 19, 8, 24],
                'backgroundColor' => 'rgba(54, 162, 235, 0.2)',
                'borderColor' => 'rgba(54, 162, 235, 1)',
                'borderWidth' => 2,
                'fill' => false,
            ],
        ])
        ->options([
            'responsive' => true,
            'maintainAspectRatio' => false,
            'legend' => ['display' => false],
        ]);

    return view('dashboard', compact('chart'));
}
<div style="height: 320px;">
    {!! $chart->render() !!}
</div>

render() emits the <canvas> plus the inline new Chart(...) bootstrap. Note the unescaped Blade echo — it is markup, not a string.

Where to look first

  1. The README on GitHub — it is the only real documentation and the examples are copy-paste ready.
  2. vendor/fx3costa/laravelchartjs/src/ChartBuilder.php — the fluent API is small; read it end to end (10 minutes) and you know the whole package.
  3. The published config file — it controls the Chart.js source/version injected into the page.
  4. The package's Blade/view stub, if published, when you need to change how the canvas is wrapped.

Implementation Patterns

Keep chart construction out of views. The fluent builder returns a mutable object; treat it like a DTO. Two clean options:

  • Controller method for one-off charts.
  • Dedicated class per chart (App\Charts\RevenueChart with a build() method) once you pass ~3 charts. This makes them unit-testable and keeps fat controllers thin.
class RevenueChart
{
    public function build(array $rows)
    {
        return Chartjs::name('revenue')
            ->type('bar')
            ->labels(array_column($rows, 'month'))
            ->datasets([[
                'label' => 'Revenue',
                'data'  => array_column($rows, 'total'),
                'backgroundColor' => '#4e73df',
            ]])
            ->options(['scales' => ['yAxes' => [['ticks' => ['beginAtZero' => true]]]]]);
    }
}

Multiple charts on one page. Each call to Chartjs::name() must use a unique name — the name becomes the canvas id and the JS lookup key. Loop over a collection of pre-built charts in the view:

@foreach ($charts as $chart)
    <div class="card"><div style="height:300px">{!! $chart->render() !!}</div></div>
@endforeach

Multi-dataset and mixed charts. datasets() accepts any array of arrays; Chart.js v2 supports per-dataset type so you can overlay a line on bars:

->datasets([
    ['type' => 'bar',  'label' => 'Orders',   'data' => [10, 20, 30]],
    ['type' => 'line', 'label' => 'Forecast', 'data' => [12, 18, 33], 'fill' => false],
])

Aggregating data. Do the grouping in SQL, not PHP:

$rows = Order::selectRaw('DATE_FORMAT(created_at, "%Y-%m") as month, SUM(total) as total')
    ->groupBy('month')->orderBy('month')->get();

AJAX / filter-driven charts. The package renders server-side once; it does not react to filters. Two viable patterns:

  1. Full page reload / partial refresh — rebuild the chart server-side and swap the container's HTML. Simplest, and fine for dashboards.
  2. JSON endpoint + hand-written Chart.js — return ['labels' => ..., 'datasets' => ...] from an API route, then call chart.data = payload; chart.update(); in JS, keeping a reference to the instance you created. Use the package for the initial paint, plain Chart.js for updates.

Layout. Always give the canvas a bounded parent with an explicit height and set maintainAspectRatio => false; otherwise the chart grows unbounded on resize and inside flex/grid children.

Gotchas and Tips

Chart.js v2 only. This wraps Chart.js 2.x. If your app already loads Chart.js 3/4 via npm or another CDN, you get two global Chart definitions and one of them wins silently — charts render blank or with v3-incompatible options ignored. Audit window.Chart in the console. v2 is EOL; for new work, consider Chart.js 4 directly or a maintained wrapper.

The JS comes from a CDN. Rendering assumes network access at page load, which breaks offline/intranet deployments and needs the CDN host in your CSP script-src. There is no SRI hash. For production, download the pinned Chart.js build, host it yourself, and adjust the config so the package points at your asset path — or drop the package's script injection and include Chart.js in your own bundle.

Duplicate canvas IDs. Reusing the same name — e.g. two Chartjs::name('chart') calls in a loop without varying the name — produces duplicate id attributes. The browser binds the script to the first element only, so the second container stays blank while the first chart quietly redraws. Generate names like "revenue-{$tenant->id}" and Str::slug() them.

Collections and value types. ->labels($collection) generally works because Collection is JsonSerializable, but pluck() on an Eloquent collection can surface model attributes or unexpected keys — call ->values()->all() to guarantee a plain list. Database decimals and SUM() results often arrive as strings ("1234.50"), which Chart.js v2 will happily plot as category labels rather than numbers. Cast with (float) or ->map(fn ($v) => (float) $v).

Pass options as arrays, never JSON strings. Passing json_encode([...]) gives you a quoted string inside the generated options object and the chart ignores everything. Same for nested keys — Chart.js v2 uses plural scales, xAxes/yAxes (v3+ renamed these to x/y), and legend not plugins.legend.

Escaping. {!! $chart->render() !!} is required, and json_encode escapes / by default so a </script> in a label will not break out — but do not rely on that for arbitrary user input. Sanitize label text; anything echoed raw into a <script> context is a risk you should consciously accept.

Payload size. Every chart embeds its full dataset as inline JSON. A few thousand points will bloat the HTML and delay first paint. For large series, downsample server-side, paginate the time window, or move to the AJAX pattern.

Modern Laravel compatibility. Check the composer.json constraint before promising this to a team. The package targets Laravel 5.x; on Laravel 9/10/11 Composer may refuse to install and you'll be choosing between --ignore-platform-reqs (works, but unverified) and a fork. Given 0 dependents and a 2023 last release, budget for the possibility of maintaining a fork — it is a ~300-line wrapper, so forking is cheap.

Debugging checklist. View source and confirm: (a) exactly one <script src="...chart.js"> tag, (b) the canvas id matches the getElementById in the inline script, (c) the JSON blob parses (paste it into the console), (d) typeof Chart !== 'undefined' before your inline script runs. Console errors of Chart is not defined almost always mean the CDN was blocked.

Testing. Assert on the canvas id and the serialized data rather than the markup:

$response->assertSee('id="signups"', false);
$response->assertSee('"data":[12,19,8,24]', false);

Extension points. Publish the config/views to change the injected script tag or wrapper markup; wrap the facade behind your own ChartFactory so you can swap implementations later without touching every controller.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo