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

Filament Echarts Laravel Package

elemind/filament-echarts

Filament ECharts integrates Apache ECharts into Laravel Filament panels, making it easy to add beautiful, interactive, customizable charts and widgets with a simple PHP API. Ideal for dashboards, reports, and responsive data visualizations.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and register. Pull the package in via Composer and let Filament's asset pipeline pick up the ECharts JS bundle:

composer require elemind/filament-echarts
php artisan filament:assets

If the package ships a config file (config/filament-echarts.php), publish it only when you actually need to change defaults — CDN vs. bundled assets, default theme, height. Check the README first; the package is small (15 stars, single maintainer), so the source itself is the most reliable documentation and is short enough to read end-to-end in ten minutes.

Where to look first.

  1. src/ — the widget base class you extend and the Blade view that mounts the chart. This tells you the exact property/method names (getOption(), $heading, $chartHeight, etc.).
  2. The package's own demo/tests, if present — they show the canonical Filament resource integration.
  3. README.md for the Filament version constraint (v3 vs v4 matters a lot here).

First use case: a dashboard KPI chart. The lowest-friction win is a line or bar chart on a Filament dashboard page. Create a widget:

php artisan make:filament-widget RevenueChart --chart

Then swap the base class for the package's ECharts widget and return a raw ECharts option array:

use Elemind\FilamentEcharts\Widgets\EChartsWidget;

class RevenueChart extends EChartsWidget
{
    protected static ?string $heading = 'Revenue (30d)';
    protected int|string|array $columnSpan = 'full';

    protected function getOption(): array
    {
        return [
            'tooltip' => ['trigger' => 'axis'],
            'xAxis' => ['type' => 'category', 'data' => $this->labels()],
            'yAxis' => ['type' => 'value'],
            'series' => [[
                'type' => 'line',
                'smooth' => true,
                'data' => $this->values(),
            ]],
        ];
    }
}

Register it on a page via getWidgets() or getHeaderWidgets(). If the chart renders at zero height, you've hit the most common onboarding snag — set an explicit height either in the widget or the config.

Implementation Patterns

Treat the option array as the contract. The whole value proposition is that you hand Apache ECharts a PHP array and it becomes a chart. Keep that boundary clean:

  • Build options in a dedicated method or a small ChartOption builder class, not inline in the widget.
  • Never echo JSON into Blade by hand; use the package's option property so Livewire re-renders stay in sync.
  • For datasets with many points, prefer dataset + encode over parallel xAxis.data/series.data arrays — it maps naturally to an Eloquent collection and is far less code.

Data flow pattern: query → transform → option. The most maintainable shape is a thin widget that delegates:

protected function getOption(): array
{
    return [
        'dataset' => ['source' => $this->orders()->map(fn ($o) => [
            'date'  => $o->date->format('Y-m-d'),
            'total' => (float) $o->total,
        ])->all()],
        'xAxis' => ['type' => 'category'],
        'yAxis' => ['type' => 'value'],
        'series' => [['type' => 'bar', 'encode' => ['x' => 'date', 'y' => 'total']]],
    ];
}

Multi-widget dashboards. Because each widget is a normal Filament widget, you get $columnSpan, $pollingInterval, filters, and lazy loading for free. Use polling sparingly — every tick re-serialises the whole option array and re-creates the ECharts instance unless the package diffs options (check the view; many ECharts bridges just call setOption which is cheap, but a full re-init is not).

Interactive filtering. The idiomatic Filament approach is to put a Select/DatePicker form on the page or widget, store the value in a public Livewire property, and recompute getOption() from it. The widget re-renders and the chart updates. Avoid client-side JS event wiring into Livewire unless the package explicitly documents a bridge — it's the fastest way to create stale-state bugs.

Composable chart types. Standard patterns that pay off repeatedly:

  • Sparkline-style KPI cards — tiny type: 'line' widget with axes hidden, embedded in a custom dashboard view.
  • Stacked bars for cohort/retention — stack: 'total' on each series plus legend.
  • Drill-down via Filament page links — use ECharts' click events only if the package exposes a JS hook; otherwise link out from a table beneath the chart.
  • Comparison charts — same option builder, two series, tooltip.trigger = 'axis'.

Reuse across resources. Extract per-domain option builders (SalesChartOptions, UserGrowthChartOptions) and inject them, so a dashboard widget and a resource-page widget share one definition. This is the single biggest maintainability lever on a package this thin.

Dark mode. Filament themes toggle a dark class on <html>. ECharts needs its text/axis colours set explicitly or it will render dark text on a dark card. Either register an ECharts theme and have the widget pick it based on Filament::getCurrentPanel()->hasDarkMode(), or set textStyle.color from a CSS variable read server-side. Test both modes before shipping.

Gotchas and Tips

Version-matrix risk. With 15 stars and zero dependents, this is a single-maintainer package. Pin the version in composer.json and confirm the Filament major version in the README before adopting. Filament's widget API churned between v3 and v4 (getStats, panel asset registration, FilamentView), so a package that supports both will have conditional code paths worth reading.

Zero-height / blank chart. By far the most common failure. ECharts requires the container to have a resolved height; a Filament widget card with height: 100% inside an auto-height parent collapses. Fix by setting an explicit pixel or rem height on the chart container (usually a package config or widget property) and, if inside a grid, ensuring the parent grid row has a definite height.

Asset loading and ordering. ECharts must load before the init script. If you're using Filament's asset registration, verify with the browser network tab that echarts.min.js loads once and not per-widget. On slow connections, a race between Livewire's morph and echarts.init produces "instance already initialized" console warnings — the symptom is a chart that draws once and then dies on the next poll. Look for an echarts.getInstanceByDom(el)?.dispose() guard in the package's JS; if absent, that's your patch point.

Livewire re-render behaviour. Options returned from PHP get serialised into the DOM and re-applied on morph. Large datasets (10k+ points) will balloon the Livewire payload and make every poll expensive. For big series, downsample server-side (LTTB or simple bucketing) or send a data URL and fetch it from JS. Also beware: PHP json_encode turns floats into strings in some configs — cast monetary values to (float) explicitly or axes will mis-scale.

Debugging. When the chart is blank, in order: (1) view source — is the option JSON present and valid? (2) console — does echarts exist? (3) does echarts.init(el).setOption(JSON.parse(...)) work manually in the console with the same payload? That three-step isolates PHP-side vs JS-side vs CSS-layout issues in under a minute. Note that ECharts fails silently on malformed options in many cases — a console.warn is often the only signal.

Extension points. The package is deliberately thin, so extend by wrapping, not forking: subclass the widget to add shared defaults (grid margins, palette, animation), publish the Blade view to inject echarts.registerTheme() calls or a resize observer, and keep the fork surface as small as possible. If you need a feature the package doesn't have (e.g. server-side image export, WebGL series), it's usually faster to emit the raw option array from your own Blade partial than to wait on upstream.

Timezone and locale. ECharts formats dates client-side using browser locale; if you pass pre-formatted Y-m-d strings from PHP you control this, but if you pass timestamps and rely on axisLabel.formatter, server and user timezones will disagree. Format server-side for anything audit-facing.

Accessibility and print. Add 'aria' => ['enabled' => true] to the option for screen readers. For PDF/print dashboards, ECharts canvases don't print reliably — either enable the SVG renderer ('renderer' => 'svg' if the package exposes it) or provide getDataAsTable() fallbacks.

Budget a fallback. Given the dependency count is zero and the star count is low, keep a short internal note on how to drop to plain echarts + a Blade partial if the package stalls on a future Filament release. Because the option array is ECharts' native format, that migration is a couple of hours, not a rewrite — which is the strongest argument for adopting this package in the first place.

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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin