DEV Community

Imam Ali Mustofa
Imam Ali Mustofa

Posted on • Originally published at darkterminal.prose.sh

Lazy as F! Isn’t About D.R.Y but B.A.F When Creating ChartJS

Hello Punk! I am again… Yes the Software Freestyle Engineer! Too handsome and stupid from the first time you think who am I.

What I want to share about the title above “Lazy as F! Isn’t About D.R.Y but B.A.F When Creating ChartJS”?

Let me tell to you…

What The D.R.Y?

Yes! As you expect! Thank you very much…

What The B.A.F Mean?

Boring As F! Thank you very much again. I think I am too handsome for doing the kinda stuff over and over in ChartJS! So, I creating component (yes, if you think kind of React-things) like using HTML. For efficiency:

<?php
// Filename: /home/darkterminal/workspace/fck-htmx/app/config/ChartJS.php

namespace App\config\helpers;

class ChartJS
{
    private $type;
    private $data;
    private $options;

    public function __construct($type, $customOptions = [])
    {
        $this->type = $type;
        $this->data = [
            'labels' => [],
            'datasets' => []
        ];

        $defaultOptions = [
            'responsive' => true,
            'plugins' => [
                'title' => [
                    'display' => true,
                    'text' => 'Chart.js ' . ucfirst($type) . ' Chart'
                ]
            ]
        ];
        $this->options = array_replace_recursive($defaultOptions, $customOptions);
    }

    public function addLabel($label)
    {
        $this->data['labels'][] = $label;
        return $this;
    }

    public function addDataset($label, $data, $backgroundColor, $borderColor, $additionalOptions = [])
    {
        $dataset = [
            'label' => $label,
            'data' => $data,
            'backgroundColor' => $backgroundColor,
            'borderColor' => $borderColor
        ];

        $dataset = array_merge($dataset, $additionalOptions);

        $this->data['datasets'][] = $dataset;
        return $this;
    }

    public function setOptions($options)
    {
        $this->options = array_merge_recursive($this->options, $options);
        return $this;
    }

    public function getChartConfig()
    {
        return [
            'type' => $this->type,
            'data' => $this->data,
            'options' => $this->options
        ];
    }

    public function create(array $chartConfig, string $canvasName = 'myChart')
    {
        $html = '<div class="w-full">
                <canvas id="' . $canvasName . '"></canvas>
            </div>
            <script type="module">
                import {
                    Chart,
                    registerables
                } from \'https://cdn.jsdelivr.net/npm/chart.js@4.4.2/+esm\';
                Chart.register(...registerables);
                const ctx = document.getElementById(\'' . $canvasName . '\');

                if (ctx) {
                    new Chart(ctx, ' . json_encode($chartConfig) . ');
                } else {
                    console.error(\'Canvas element with ID: ' . $canvasName . ' not found.\');
                }
            </script>';

        return $html;
    }
}

Enter fullscreen mode Exit fullscreen mode

I am a simple man and to the point! So, I created this ChartJS Class to wrap up the boring stuff and avoid switching between PHP and JavaScript over and over again. You know what I mean, right? Just say “Yes!” please…

I am a Software Engineer specializing in freestyle development, building web applications using PHP and HTMX. Therefore, I need to focus on writing less JavaScript code and shifting my state mindset to the server.

The Class Usage

Instead of writing a bunch of JSON, I just need to write in my own preferred language (it's not a language, some people say from the background). Yes, PHP! That's part of Hypermedia, so I write using it.

PHP Hypertext Preprocessor

<?php
// Filename: /home/darkterminal/workspace/fck-htmx/views/components/dashboard/partials/ritail.chart.php

use App\config\helpers\ChartJS;

$overrideOptions = [
    'responsive' => true,
    'plugins' => [
        'legend' => [
            'display' => false
        ],
        'title' => [
            'display' => false,
            'text' => 'Ritail Chart'
        ]
    ]
];

$chartJS = new ChartJS('line', $overrideOptions);

$chartConfig = $chartJS->addLabel('January')
    ->addLabel('February')
    ->addLabel('March')
    ->addDataset('Dataset 1', [65, 59, 80], 'rgba(75, 192, 192, 0.2)', 'rgb(75, 192, 192)')
    ->addDataset('Dataset 2', [28, 48, 40], 'rgba(54, 162, 235, 0.2)', 'rgb(54, 162, 235)')
    ->setOptions([
        'scales' => [
            'y' => [
                'beginAtZero' => true
            ]
        ],
        'elements' => [
            'line' => [
                'tension' => 0.4
            ]
        ]
    ])
    ->getChartConfig();

$chartHTML = $chartJS->create($chartConfig, 'ritailChart');

echo $chartHTML;

Enter fullscreen mode Exit fullscreen mode

Did you see that!?

  • Defined the options overrides (optional)
  • Create ChartJS instance and define the chart type
  • Add all what you need, Label, Datasets, chart configs
  • and generate that code, add an id to draw the chart

That's it! You're welcome…

Top comments (0)