radiatecode/dachartjs

Chart js back-end service for laravel

v1.0.0 2021-12-30 19:45 UTC

This package is auto-updated.

Last update: 2024-10-05 22:15:06 UTC


README

Stats

Latest Version on Packagist Total Downloads

The package used to generate charts in Laravel without implementing javascript in the front-side. It is used as a back-end service of chart js. It will dynamically render HTML & JS configuration.

Examples

Example 1: Monthly Project, Task and Issue Completion Chart

Stats

Chart Class

namespace App\Charts;

use RadiateCode\DaChartjs\Abstracts\AbstractChart;
use RadiateCode\DaChartjs\Facades\Dataset;
use RadiateCode\DaChartjs\Types\Bar\VerticalBarChart;

class MonthlyChart extends AbstractChart
{
    protected function chartTitle(): string
    {
        return 'Month Chart';
    }

    protected function chartType(): string
    {
        return VerticalBarChart::class;
    }

    protected function labels(): array
    {
        return ['January','February','March'];
    }

    protected function datasets(): array
    {
        return [
            Dataset::general('Project',[20, 30,55])->make(),
            Dataset::general('Task',[50, 80,44])->make(),
            Dataset::general('Task',[70, 75,99])->make()
        ];
    }
}

In controller:

use App\Charts\MonthlyChart;

class ReportController extends Controller 
{  
    public function monthlyChart()
    {
        $monthlyChart = new MonthlyChart();
        
        return view('reports.monthly')->with('monthlyChart',$monthlyChart->template());
    }
}

In view (blade) file:

<div class="chart">
    <!-- generate chart html canvas -->
    {!! $monthlyChart->chartHtml() !!}
</div>

......
<!-- generate chart js CDN scripts -->
{!! $monthlyChart->chartLibraries() !!}
<!-- generate chart configured scripts -->
{!! $monthlyChart->chartScripts() !!}

Example 2: API or AJAX Chart

Stats

The chart shows top sales products according to the month selection.

Chart Class

namespace App\Charts;

use RadiateCode\DaChartjs\Abstracts\AbstractChart;
use RadiateCode\DaChartjs\Types\Bar\VerticalBarChart;

class SalesChart extends AbstractChart
{
    protected function chartTitle(): string
    {
        return 'Monthly Sales Chart';
    }

    protected function chartType(): string
    {
        return VerticalBarChart::class;
    }

    protected function labels(): array
    {
        return []; // empty labels, will be loaded by ajax
    }

    protected function datasets(): array
    {
        return []; // empty datasets, will be loaded by ajax
    }
}

In controller:

use App\Charts\SalesChart;

class ReportController extends Controller 
{
    public function salesChart(){
        $monthlySalesChart = new SalesChart();
        
        return view('reports.top_sales')->with('monthlySalesChart',$monthlySalesChart->template());
    }
}

In blade file:

<div class="chart">
    <input type="text" id="month_name" class="form-control month" placeholder="" aria-label="">
    <button class="btn btn-primary" id="search-btn" type="button">
        <i class="fa fa-search-plus"></i>
    </button>
    <!-- generate chart html canvas -->
    {!! $monthlySalesChart->chartHtml() !!}
</div>

......
<!-- generate chart js CDN scripts -->
{!! $monthlySalesChart->chartLibraries() !!}
<!-- generate ajax chart scripts -->
{!! $monthlySalesChart->apiChartScripts(url('fetch/monthly/top/sales/chart'), 'search-btn', ["month_name"]) !!}

When "search-btn" is triggered it will get value from input element of month, attach the value with the given url as query string and send request to server to fetch data.

Api Route:

Route::get('fetch/monthly/top/sales/chart','ReportController@monthlyTopSales');

Api Response:

use RadiateCode\DaChartjs\Facades\Dataset;
use RadiateCode\DaChartjs\Facades\ChartResponse;
use RadiateCode\DaChartjs\Enums\ChartColor;
use App\Models\Order;

class ReportController extends Controller 
{
    public function monthlyTopSales(Request $request)
    {
        $sales = Order::where('month',$request->get('month_name'))
                        ->orderBy('sold_qty','desc')
                        ->groupBy('product_id')
                        ->selectRaw('product_name, SUM(qty) as sold_qty')
                        ->take(4)->get();
                        
         $soldProducts = $sales->pluck('product_name')->toArray();
         $soldQty = $sales->pluck('sold_qty')->toArray();
    
         $datasets = [
            Dataset::label('Top Sales')
                ->data($soldQty)
                ->backgroundColor([
                    ChartColor::LIGHT_SLATE_BLUE,
                    ChartColor::BRIGHT_TURQUOISE,
                    ChartColor::ELECTRIC_PURPLE,
                    ChartColor::EGGPLANT
                ])->make(),
        ];
        
        return ChartResponse::labels($soldProducts)->datasets($datasets)->toJson();
    }
}

Requirements

Installation

You can install the package via composer:

composer require radiatecode/dachartjs

Register Service Provider (Optional on Laravel 5.5+)

Register provider on your config/app.php file.

'providers' => [
    ...,
    RadiateCode\DaChartjs\ChartServiceProvider::class,
]

Usages

In two ways you can generate chart such as

Generate chart by dedicated class

Run the command to create a chart class

php artisan make:dachartjs MonthlyCompletionChart

This will create a dedicated chart class under App\Charts namespace.

Sample Code:

namespace App\Charts;

use RadiateCode\DaChartjs\Abstracts\AbstractChart;
use RadiateCode\DaChartjs\Facades\Dataset;
use RadiateCode\DaChartjs\Types\Bar\HorizontalBarChart;

class MonthlyCompletionChart extends AbstractChart
{
	/**
     * Chart title
     *
     * ---------------------------------------------------------------------
     * Note: it can be use as chart id or chart name in js & html
     * ---------------------------------------------------------------------
     * @return string
     */
    protected function chartTitle(): string
    {
        return 'Month Chart';
    }

	/**
     * Chart type
     *
     * ---------------------------------------------------------------------
     * Note: Chart type must be path of a concrete class of TypeInterface
     * [ex: HorizontalBarChart::class]
     * ---------------------------------------------------------------------
     * @return string
     */
    protected function chartType(): string
    {
        return HorizontalBarChart::class;
    }

    /**
     * Chart labels
     *
     * -----------------------------------------------------------------------
     * Note: This labels are used to label the data index (default x axis)
     * -----------------------------------------------------------------------
     * @return array
     */
    protected function labels(): array
    {
        return ['January','February','March'];
    }

     /**
     * Dataset
     *
     * --------------------------------------------------------------
     * Note: datasets can be generate by Dataset Facade 
     * Or, we can pass custom array with dataset properties,
     * --------------------------------------------------------------
     * @return array
     */
    protected function datasets(): array
    {
        return [
            Dataset::general('Project',[20, 30,55])->make(),
            Dataset::general('Task',[50, 80,44])->make(),
            Dataset::general('Task',[70, 75,99])->make()
        ];
    }
}

Note: HorizontalBarChart::class has some predefined default options. So if you want to change the default options then override changeDefaultOptions().

class MonthlyCompletionChart extends AbstractChart
{
    /**
    * Change default options when necessary
    *
    * @override method
    * @return array
    */  
    protected function changeDefaultOptions(): array
    {
        return [
             // dot used in key is to indicate nested array level of option properties
            'plugins.title.text' => 'Monthly Completion Chart',
            'plugins.title.color' => 'red',
        ];
    }
}

Or, if you want to provide custom options instead of default options then override options().

class MonthlyCompletionChart extends AbstractChart
{
    /**
    * Use custom options if we don't want to use defaults
    *
    * @override method
    * @return array|string
    */  
    protected function options()
    {
         return [
                'responsive' => true,
                'scales' => [
                    'xAxes' => [
                        'ticks' => [
                            'beginAtZero' => true,
                            'maxRotation' => 90,
                            'minRotation' => 90
                        ]
                    ]
                ],
                'plugins'    => [
                    'title'  => [
                        'text'     => 'My Chart Title',
                        'position' => 'top',
                        'display'  => true,
                        'color'    => 'yellow',
                    ],
                ]
            ];
           
           /** 
           * Json string can be use
           */
           // return "{
           //   responsive : true,
           //   plugins    : {
           //       title  : {
           //           text     : 'My Chart Title',
           //           position : 'top',
           //           display  : true,
           //           color    : 'yellow',
           //       },
           //  },
           // }"
    }
}

Note: If you want to define chart size override chartSize()

 protected function chartSize(): array
   {
       return [
           'height' => 230
           // 'width' => 400 // width is optional for responsive chart
       ];
   }

In controller:

After all the configuration you can use the dedicated class in the controller

use App\Charts\MonthlyCompletionChart;

class ReportController extends Controller
{
    public function monthlyChart(){
        $myChart =  new MonthlyCompletionChart();
        
        return view('reports.monthly')->with('myChart',$myChart->template());
    }
}

Dedicated chart class object provides two methods

  • render(): Render method will return array of chart configurations. The configuration later can be manually used in javascript
  • template(): Template method return a html builder instance

In view (blade) file:

<div class="chart">
    <div class="chart">
        <!-- generate chart html canvas -->
        {!! $myChart->chartHtml() !!}
    </div>
</div>

......

<!-- generate chart.js CDN scripts-->
{!! $myChart->chartLibraries() !!}

<!-- generate configured chart script -->
{!! $myChart->chartScripts() !!}

Generate chart by service

use RadiateCode\DaChartjs\Chart;
use RadiateCode\DaChartjs\Types\Bar\HorizontalBarChart;
...................

$barChart = (new Chart('Monthly Chart', HorizontalBarChart::class))
        ->labels(['January', 'February','March']) //labeling the data index of the chart
        ->datasets([ // Datasets build by Dataset facade
            Dataset::label('Task')->data([20, 30,55])->backgroundColor('yellow')
            ->borderColor('black')->make(),
            Dataset::label('Project')->data([50, 80,44])->backgroundColor('green')
                ->borderColor('white')->make(),
            Dataset::label('Issue')->data([70, 75,99])->backgroundColor('red')
                ->borderColor('white')->make(),
        ])
        ->template();

Available Methods of Chart service class:

1. build()

Create chart service instance in a static way.

// example
Chart::build('title',HorizontalBarChart::class)->labels([])->datasets([])

It could be helpful if we want to avoid creating chart instance like new Chart()

2. labels()

labeling the data index of the chart. it could be x-axis or y-axis, by default it is x-axis.

labels axis change by indexAxis property which used in the options configuration

3. datasets()

Datasets can be build by Dataset Facades

$barChart->datasets([
    Dataset::label('Task')->data([20, 30,55])->backgroundColor('yellow')
        ->borderColor('black')->make(),
    Dataset::label('Project')->data([50, 80,44])->backgroundColor('green')
        ->borderColor('white')->make(),
    Dataset::label('Issue')->data([70, 75,99])->backgroundColor('red')
        ->borderColor('white')->make(),
]);

Or datasets can be configured as raw array

$barChart->datasets(
    [
        [
            "label"           => "Task",
            "backgroundColor" => "yellow",
            "data"            => [20, 30,55],
            "borderColor"     => "yellow",
        ],
        [
            "label"           => "Project",
            "backgroundColor" => "green",
            "data"            => [50, 80,44],
            "borderColor"     => "green",
        ],
        [
            "label"           => "Issue",
            "backgroundColor" => "red",
            "data"            => [70, 75,99],
            "borderColor"     => "red",
        ],
    ]
);

4. changeDefaultOption() [Optional]

Each type of chart class has some predefined default options. For example see the defaultOptions() methods of HorizontalBarChart , MultiAxisLineChart

So, in some scenario you may need to update the values of default options. In that case you can use changeDefaultOption('optionKey','value')

// example
$barChart->changeDefaultOption('plugins.title.text','Monthly Project, Task And Issue Chart')
        ->changeDefaultOption('plugins.title.color','blue')

Note: dot used in key arg is to indicate the nested array level of the options. The method only works when the options are in php array format

5. options() [Optional]

If you don't want to use default options then use your custom options

You can pass php array format options

$barChart->options([
        'responsive' => false,
        'plugins'    => [
            'legend' => [
                'display'  => true,
                'position' => 'top',
            ],
            'title'  => [
                'text'     => 'Custom Title',
                'position' => 'top',
                'display'  => true,
                'color'    => 'black',
            ],
        ],
    ])

Or, you can pass json string format options

$barChart->options("{
        responsive : false,
        plugins    : {
            legend : {
                display  : true,
                position : 'top',
            },
            title  : {
                text     : 'Custom Title',
                position : 'top',
                display  : true,
                color    : 'black',
            },
        },
    }")

To know more about the options properties see chart js official documentation.

6. size() [Optional]

Chart size

$barChart->size($height,$width = null)

Width is optional for responsive chart

6. render()

Render method will return array of chart configurations. The configuration later can be manually used in javascript

Check the sample code here

7. template()

If you don't want to setup javascript manually in view file then use template() instead of render(). Template method return a html builder instance

Methods of html builder

1. chartHtml() : Generate html canvas tag

2. chartLibraries() : Generate the chart js CDN scripts

3. chartScripts() : Generate chart with back-end configuration and data

Check the sample code here

4. apiChartScripts($ajaxOptions, string $clickEventId = null, array $inputElementIds = []) : Generate chart with back-end configuration. It loads chart data & labels via ajax. It also allows update or refresh the chart via firing click event.

For api response you have to use ChartResponse Facade

load chart data by ajax: If you just want to load chart data by ajax then only pass value to 1st argument of apiChartScripts

1st argument accept string (url) or array of ajax options [url, type, headers]

Check the sample Code here

Update chart data by ajax: If you want to update the chart based on some input values then you have to pass a trigger ID in the 2nd argument and input IDs in the 3rd argument of apiChartScripts.

Check the sample Code here

Chart Types

There are various predefined types of chart (configured) available such as

Bar chart

Line chart

Bubble chart

Pie chart

Doughnut chart

Polar Area Chart

Radar Chart

Scatter Chart

You can create your own custom type by extending BaseChartType. Namespace could be App\Charts\Types (create Charts\Types folder inside the app folder)

Dataset Facade

Dataset Facade can be helpful to generate datasets for chart, each dataset has various properties such as label, background color, border color, data, fill, boarder width etc. Above examples or sample code shows that how to generate datasets by using Dataset Facade

Methods

See the available methods of Dataset Facade

Dedicated Dataset Class (Suggestion)

If you create a chart with multiple datasets which depends on multiple db query then it would be nicer to create a separate dataset class in order to increase the readability, maintainability of the code

Namespace could be App\Charts\Datasets (create Charts\Datasets folder inside the app folder)

Check the sample code here

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please email radiate126@gmail.com instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.