Milk Admin

Chart

Revision: 2026-01-05

The Chart plugin allows you to display graphs or tables with static or dynamic data.

Charts are managed with the Chart.js library and tables with a custom template class. This way the data structure is the same.

For tables, datasets indicate columns, while labels indicate rows. For charts, datasets indicate series, while labels indicate categories.

Quick Start (Module)

Create a module and render a chart or table directly in your page action:


<?php
namespace Modules\ChartDemo;

use App\Abstracts\AbstractModule;
use App\Attributes\RequestAction;
use App\Response;
use App\Get;

class ChartDemoModule extends AbstractModule {

    protected function configure($rule): void {
        $rule->page('chart-demo')
             ->title('Chart Demo')
             ->menu('Chart Demo', '', 'bi bi-graph-up', 50)
             ->access('admin');
    }

    #[RequestAction('home')]
    public function home(): void {
        $data = [
            'labels' => ['Jan', 'Feb', 'Mar'],
            'datasets' => [
                ['label' => 'Sales', 'data' => [12, 19, 8], 'type' => 'bar'],
                ['label' => 'Leads', 'data' => [7, 11, 5], 'type' => 'bar'],
            ],
        ];

        $chart = Get::themePlugin('chart', [
            'id' => 'sales_chart',
            'type' => 'bar',
            'data' => $data,
            'options' => [
                'legend_position' => 'top',
                'start_by_zero' => true,
            ],
        ]);

        $table = Get::themePlugin('chart', [
            'id' => 'sales_table',
            'type' => 'table',
            'data' => $data,
            'options' => [
                'preset' => 'hoverable',
                'firstCellText' => '#',
            ],
        ]);

        Response::render($chart . $table);
    }
}
    

Data Structure


{
  "labels": ["A", "B", "C"],
  "datasets": [
    { "label": "Series 1", "data": [1, 2, 3], "type": "bar" },
    { "label": "Series 2", "data": [2, 1, 4], "type": "bar" }
  ]
}
    

Table Options

  • firstCellText: text for the first cell
  • preset: additional class for the table that defines its appearance. Possible values are default, compact, dark, or hoverable
  • showLabels: show or hide labels
  • cellClass: array of classes applied to individual columns
  • itemsPerPage: rows per page (0 disables pagination)
  • headerClass: class for the table header

Chart Options (Common)

  • legend_position: top, left, bottom, right
  • start_by_zero: start Y axis from zero
  • scale_x/scale_y: set axis type or hide with hide
  • title_x/title_y: axis titles
  • height: fixed height for the chart container (e.g. 260px)

You can generate a chart or table through the chart plugin in Ito.


$data = json_decode('{"labels":[0,1,2,3],"datasets":[{"data":["78","66","42","77"],"label":"age","type":"bar"},{"data":["60","70","67","80"],"label":"weight","type":"bar"}]}', true);
echo Get::themePlugin('chart', ['id'=>'table', 'type'=>'table', 'data'=> $data, 'options'=>['preset'=>'hoverable', 'firstCellText' => 'X']]);
echo Get::themePlugin('chart', ['id'=>'chart', 'type'=>'bar', 'data'=> $data ]);
    
example table
table
Loading...
Card by SQL
Dynamic filterable data
Loading...

Table examples

<?php echo Get::themePlugin('chart', ['id'=>'noLabel', 'type'=>'table',  'data'=> $data,  
    'options'=>[
        'preset'=>'default', 
        'showLabels' => false, 
        'cellClass'=>['col-min', ''], 
        'itemsPerPage' =>2, 
        'headerClass'=>'thead-dark'
    ]]); ?>
Table without labels or pagination
Loading...
Page options
Choose the number of rows per page and the pagination position
  • itemsPerPage: number of rows per page. 0 for no pagination
  • cellClass: array of classes applied to individual columns.
  • showLabels: show or hide labels
  • preset: additional class for the table that defines its appearance. Possible values are default, compact, dark, or hoverable
  • Special classes: for columns .col-min for minimum width, .thead-dark for dark header

If you want to update the data after inserting the chart, you can manage the loading state and data update as shown in the example:


var data1 = {"labels":[0,1,2,3,4,5,6,7,8,9],"datasets":[{"data":["78","66","42","77","70","86","58","33","56","61"],"label":"age","type":"bar"},{"data":["60","70","67","80","95","71","68","65","82","84"],"label":"weight","type":"bar"}, {"data":["160","170","167","180","195","171","168","165","182","184"],"label":"height","type":"bar"}]}
function updateData(el) {
    el.disabled = true;
    itoCharts.getLoader('table').show();
    itoCharts.getLoader('chart').show();
    setTimeout(() => {
        itoCharts.update('table', data1);
        itoCharts.update('chart', data1);
        itoCharts.getLoader('table').hide();
        itoCharts.getLoader('chart').hide();
        el.disabled = false;
    }, 3000);
}
    
example table
table
Loading...
Card by SQL
Dynamic filterable data
Loading...
Loading...