DEMO / LiveComponent

Auto-Updating Chart

What do you get with Live Components + UX Chart.js + UX Autocomplete?
An auto-updating chart that you will ❤️.


Source: National History Museum courtesy of https://github.com/kjanjua26/jurassic-park
// ... use statements hidden - click to show
use App\Service\DinoStatsService;
use Symfony\UX\Chartjs\Builder\ChartBuilderInterface;
use Symfony\UX\Chartjs\Model\Chart;
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveProp;
use Symfony\UX\LiveComponent\DefaultActionTrait;
use Symfony\UX\TwigComponent\Attribute\ExposeInTemplate;

#[AsLiveComponent]
class DinoChart
{
    use DefaultActionTrait;

    #[LiveProp(writable: true)]
    public array $currentTypes = ['all', 'large theropod', 'small theropod'];

    #[LiveProp(writable: true)]
    public int $fromYear = -200;

    #[LiveProp(writable: true)]
    public int $toYear = -65;

    public function __construct(
        private DinoStatsService $dinoStatsService,
        private ChartBuilderInterface $chartBuilder,
    ) {
    }

    #[ExposeInTemplate]
    public function getChart(): Chart
    {
        $chart = $this->chartBuilder->createChart(Chart::TYPE_LINE);
        $chart->setData($this->dinoStatsService->fetchData(
            $this->fromYear,
            $this->toYear,
            $this->currentTypes
        ));

        $chart->setOptions([
            // set title plugin
            'plugins' => [
                'title' => [
                    'display' => true,
                    'text' => sprintf(
                        'Dinos species count from %dmya to %dmya',
                        abs($this->fromYear),
                        abs($this->toYear)
                    ),
                ],
                'legend' => [
                    'labels' => [
                        'boxHeight' => 20,
                        'boxWidth' => 50,
                        'padding' => 20,
                        'font' => [
                            'size' => 14,
                        ],
                    ],
                ],
            ],
            'elements' => [
                'line' => [
                    'borderWidth' => 5,
                    'tension' => 0.25,
                    'borderCapStyle' => 'round',
                    'borderJoinStyle' => 'round',
                ],
            ],
            'maintainAspectRatio' => false,
        ]);

        return $chart;
    }

    #[ExposeInTemplate]
    public function allTypes(): array
    {
        return DinoStatsService::getAllTypes();
    }
}
<div {{ attributes }}>
    <div class="row">
        <div class="col-2">
            <label for="fromYear" class="form-label">
                From: <code><small>({{ fromYear|abs }} mya)</small></code>
            </label>
            <input
                type="range"
                class="form-range"
                id="fromYear"
                data-model="fromYear"
                min="-200"
                max="{{ toYear }}"
            >
        </div>

        <div class="col-2">
            <label for="toYear" class="form-label">
                To: <code><small>({{ toYear|abs }} mya)</small></code>
            </label>
            <input
                type="range"
                class="form-range"
                id="toYear"
                data-model="toYear"
                min="{{ fromYear }}"
                max="-65"
            >
        </div>

        <div class="col-8">
            <label for="dinoTypes" class="form-label">Choose Dino Types</label>
            <select
                data-model="currentTypes"
                multiple
                id="dinoTypes"
                data-controller="symfony--ux-autocomplete--autocomplete"
            >
                {% for type in allTypes %}
                    <option value="{{ type }}">{{ type }}</option>
                {% endfor %}
            </select>
        </div>
    </div>

    <hr>

    <div style="min-height: 480px; margin-bottom: 1.5rem;">
        {{ render_chart(chart) }}
    </div>

    <small>Source:
        <a href="https://www.nhm.ac.uk/" class="link">National History Museum</a> courtesy of
        <a href="https://github.com/kjanjua26/jurassic-park" class="link">https://github.com/kjanjua26/jurassic-park</a>
    </small>

</div>