Symfony UX and ChartJS
Tags: php, ux
Published: 2020-12-08 13:27:48

Few days ago, Symfony published an [article](https://symfony.com/blog/new-in-symfony-the-ux-initiative-a-new-javascript-ecosystem-for-symfony) about a new way to implement some JS library and make the work easier for us. 
For the moment we have 5 packages :
* [Chart.jS](https://github.com/symfony/ux-chartjs)
* [Cropper.js](https://github.com/symfony/ux-cropperjs)
* [Dropzone](https://github.com/symfony/ux-dropzone)
* [LazyImage](https://github.com/symfony/ux-lazy-image)
* [Swup](https://github.com/symfony/ux-swup)

Today I'm gonna implement Chart.js in a little project. The goal is to show you the simple way to use it. Let's start !!!

##Create the project
We need Symfony flex so just create a new full project.
```
 symfony new Chart-js-project --full
```
Then install webPackEncore and Yarn (or npm).
```
composer require symfony/webpack-encore-bundle
yarn install
```
Now WebpackEncore is installed, go to your template folder and find **base.html.twig**.
In your stylesheets block add 
```twig
{{ encore_entry_link_tags('app') }}
```
 and in your javascripts block add
```twig
{{ encore_entry_script_tags('app') }}.
```

###Create our entity
We need data for **chart.js** so we are going to create an entity. Mmmh let's say we need to know (for some reasons) how many croissant🥐 we eat every day.To go faster I will use maker so let's do it.
`symfony console make:entity Croissant`
Our first field will be the number of croissant we eat every day and the second the date of day and both will not be null
```
 New property name (press <return> to stop adding fields):
 > number

 Field type (enter ? to see all types) [string]:
 > int
integer

 Can this field be null in the database (nullable) (yes/no) [no]:
 >

 updated: src/Entity/Croissant.php

 Add another property? Enter the property name (or press <return> to stop adding fields):
 > date

 Field type (enter ? to see all types) [string]:
 > datetime
datetime

 Can this field be null in the database (nullable) (yes/no) [no]:
```
Cool our entity is created. Now we need to create our Database. I let you configurate yours in the .env file.

Still with maker we are going to create and migrate in the database with those 3 lines:
`symfony console d:d:c`
`symfony console make:migration`
`symfony console d:m:m`
Check your database, you should see your entity.

###CRUD
Its a quick project so I will continue with maker. Let's create our crud
`symfony console make:crud`
and at the question `The class name of the entity to create CRUD`, say Croissant.
Finally, our entity and the database are created and our CRUD is ready. Now let's create some fake data.

Run your server and go to the page /croissant/new. For me its *http://127.0.0.1:8000/croissant/new*
Then add as much data as you want. Now let's create our graph

###Add Chart.js with Symfony UX

Right now, we just follow the [docs](https://symfony.com/blog/new-in-symfony-the-ux-initiative-a-new-javascript-ecosystem-for-symfony).
Start by adding those lines in your CLI:
```
composer update symfony/flex
yarn upgrade "@symfony/webpack-encore@^0.32.0"
composer recipes:install symfony/webpack-encore-bundle --force -v
```
Then install the bundle `composer require symfony/ux-chartjs`

I choose to create my graph in the index page, so go to your CroissantController and in your index function start by injecting  `ChartBuilderInterface $chartBuilder`

For the example we copy the code from the docs. Your controller should look like this : 

```php
use Symfony\UX\Chartjs\Builder\ChartBuilderInterface;
use Symfony\UX\Chartjs\Model\Chart;

    /**
     * @Route("/", name="croissant_index", methods={"GET"})
     */
    public function index(CroissantRepository $croissantRepository, ChartBuilderInterface $chartBuilder): Response
    {
        $chart = $chartBuilder->createChart(Chart::TYPE_LINE);
        $chart->setData([
            'labels' => ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
            'datasets' => [
                [
                    'label' => 'My First dataset',
                    'backgroundColor' => 'rgb(255, 99, 132)',
                    'borderColor' => 'rgb(255, 99, 132)',
                    'data' => [0, 10, 5, 2, 20, 30, 45],
                ],
            ],
        ]);

        $chart->setOptions([/* ... */]);

        return $this->render('croissant/index.html.twig', [
            'croissants' => $croissantRepository->findAll(),
            'chart' => $chart,
        ]);
    }
```
For the moment you see nothing but just go in your index template and add where you want ( I just place it below the block body) `{{ render_chart(chart) }}`
Now if you go to *http://127.0.0.1:8000/croissant/*, you should see a graph. Of course the data is not ours but you're gonna work on it.

###Adding our data
So what we need to display our data ? We need the number of croissant we ate and the day we did it.
We are going to modify the 'labels' with the date of our data and 'data' with the number of croissant we ate.
Start by creating 2 empty arrays.
```php
$labels = [];
$datasets = [];
```
Then we fetch all the data by doing `$repo = $croissantRepository->findAll();`.
Ok, now, foreach data we want the date and the number of croissants. So let's do the loop and adding the data in our variables:
```php
foreach($repo as $data){
            $labels[] = $data->getDate()->format('d-m-Y');
            $datasets[] = $data->getNumber();
        }
```
For the date I choose the French format 🥐🥖🍷🧀. 
And now, just replace the fake data in 'labels' by `$labels` and the fake data in 'data' by `$datasets`.And that's it, now if you go to *http://127.0.0.1:8000/croissant/* you will see your wonderfull graph. Just modify the style and personalize it as you want. You can add some options if you want but for this example I choose to not add it and I deleted it.
Your final code should look like this :
```php
/**
     * @Route("/", name="croissant_index", methods={"GET"})
     */
    public function index(CroissantRepository $croissantRepository, ChartBuilderInterface $chartBuilder): Response
    {
        $labels = [];
        $datasets = [];
        $repo = $croissantRepository->findAll();
        foreach($repo as $data){
            $labels[] = $data->getDate()->format('d-m-Y');
            $datasets[] = $data->getNumber();
        }
        $chart = $chartBuilder->createChart(Chart::TYPE_LINE);
        $chart->setData([
            'labels' => $labels,
            'datasets' => [
                [
                    'label' => 'My First dataset',
                    'backgroundColor' => 'rgb(255, 99, 132)',
                    'borderColor' => 'rgb(255, 99, 132)',
                    'data' => $datasets,

                ]
            ],
        ]);
        return $this->render('croissant/index.html.twig', [
            'croissants' => $croissantRepository->findAll(),
            'chart' => $chart,
        ]);
    }
```
You can change the look of your graph by changing the `Chart::TYPE_LINE` by an other type. This is the list :
*TYPE_LINE
*TYPE_BAR
*TYPE_RADAR
*TYPE_PIE
*TYPE_DOUGHNUT
*TYPE_POLAR_AREA
*TYPE_BUBBLE
*TYPE_SCATTER

I hope you liked the article 😉

That's all folks !