Di tutorial sebelumnya, kita sudah menampilkan data sederhana dari database ke grafik menggunakan Chart.js. Jika belum membaca tutorial sebelumnya tentang Menampilkan data dari database MySQL ke grafik di Laravel menggunakan Chart.js, bisa pelajari dulu agar lebih mudah memahami tutorial ini. Pada tutorial ini, kita akan menampilkan data dari tabel yang sama (sales), tetapi dengan beberapa fitur tambahan untuk membuat grafik lebih interaktif dan dinamis.
Fitur yang Akan Kita Buat:
Multiple Datasets: Menampilkan lebih dari satu set data pada grafik, misalnya menampilkan penjualan produk per bulan.
Filter Grafik Berdasarkan Rentang Waktu: Membuat filter untuk menampilkan data berdasarkan bulan atau tahun tertentu.
Dynamic Loading dengan AJAX: Memuat data secara dinamis tanpa perlu refresh halaman.
Langkah 1: Install Laravel dan Setup Database (Jika Belum Ada)
Jika Anda sudah mengikuti tutorial sebelumnya, Anda sudah memiliki model Sale dan tabel sales dengan data penjualan. Jika belum, ikuti langkah berikut untuk setup dasar Laravel dan database.
composer create-project --prefer-dist laravel/laravel laravel-chart
php artisan make:model Sale -m
Langkah 2: Update Tabel sales dengan Kolom month dan year
Kita perlu menambahkan kolom month dan year di tabel sales agar bisa memfilter data penjualan berdasarkan bulan dan tahun. Tambahkan kolom ini di migration:
public function up()
{
Schema::create('sales', function (Blueprint $table) {
$table->id();
$table->string('product_name');
$table->integer('quantity');
$table->integer('month'); // Tambahkan kolom bulan
$table->integer('year'); // Tambahkan kolom tahun
$table->timestamps();
});
}
Setelah itu, jalankan perintah migrasi:
php artisan migrate
Langkah 3: Isi Data Penjualan Secara Dinamis
Sekarang kita tambahkan data penjualan ke tabel sales untuk beberapa bulan dan tahun yang berbeda. Gunakan seeder atau isi data secara manual di database. Buat seeder dengan perintah
php artisan make:seeder SalesTableSeeder
Isi data dummy di SalesTableSeeder.php:
use App\Models\Sale;
use Illuminate\Database\Seeder;
class SalesTableSeeder extends Seeder
{
public function run()
{
// Data untuk tahun 2023
Sale::create(['product_name' => 'Product A', 'quantity' => 100, 'month' => 1, 'year' => 2023]);
Sale::create(['product_name' => 'Product B', 'quantity' => 80, 'month' => 2, 'year' => 2023]);
Sale::create(['product_name' => 'Product C', 'quantity' => 90, 'month' => 1, 'year' => 2023]);
// Data untuk tahun 2024
Sale::create(['product_name' => 'Product A', 'quantity' => 120, 'month' => 1, 'year' => 2024]);
Sale::create(['product_name' => 'Product B', 'quantity' => 100, 'month' => 2, 'year' => 2024]);
Sale::create(['product_name' => 'Product C', 'quantity' => 110, 'month' => 1, 'year' => 2024]);
}
}
Jalankan seeder:
php artisan db:seed --class=SalesTableSeeder
Langkah 4: Buat Route untuk Filter Data dan Grafik
Tambahkan route untuk menampilkan halaman chart dan API yang akan digunakan untuk memfilter data dengan AJAX di routes/web.php:
use App\Http\Controllers\ChartController;
Route::get('/chart', [ChartController::class, 'index'])->name('chart.index');
Route::get('/chart/data', [ChartController::class, 'getData'])->name('chart.data');
Langkah 5: Buat Controller untuk Menangani Filter dan Fetch Data
Buka ChartController.php dan tambahkan logika untuk mengambil data dari database berdasarkan filter waktu:
namespace App\Http\Controllers;
use App\Models\Sale;
use Illuminate\Http\Request;
class ChartController extends Controller
{
public function index()
{
return view('chart');
}
// Fetch data untuk grafik berdasarkan filter waktu
public function getData(Request $request)
{
$year = $request->input('year', date('Y')); // Default ke tahun ini
$month = $request->input('month'); // Bulan bisa null untuk mengambil semua bulan
// Ambil data dari tabel sales
$query = Sale::where('year', $year);
if ($month) {
$query->where('month', $month);
}
$sales = $query->get();
// Mengelompokkan data berdasarkan produk
$groupedSales = $sales->groupBy('product_name');
$datasets = [];
foreach ($groupedSales as $productName => $sales) {
$datasets[] = [
'label' => $productName,
'data' => $sales->pluck('quantity'),
'backgroundColor' => $this->getRandomColor(),
];
}
// Kembalikan data untuk Chart.js
return response()->json([
'labels' => $sales->pluck('month')->unique(), // Label berupa bulan
'datasets' => $datasets,
]);
}
// Fungsi untuk mendapatkan warna acak
private function getRandomColor()
{
$colors = ['rgba(75, 192, 192, 0.2)', 'rgba(255, 99, 132, 0.2)', 'rgba(54, 162, 235, 0.2)'];
return $colors[array_rand($colors)];
}
}
Langkah 6: Buat View untuk Menampilkan Grafik dengan Filter
Buat file resources/views/chart.blade.php. Di file ini, kita akan menambahkan form untuk memfilter data dan menggunakan AJAX untuk memuat data ke grafik tanpa refresh halaman:
@extends('layout')
@section('title', 'Sales Chart with Filter')
@section('content')
<div class="container mt-5">
<h2 class="mb-4">Sales Data with Filter</h2>
<!-- Filter Form -->
<form id="filter-form">
<div class="form-row">
<div class="col-md-4 mb-3">
<label for="year">Year</label>
<select class="form-control" id="year" name="year">
<option value="2023">2023</option>
<option value="2024">2024</option>
</select>
</div>
<div class="col-md-4 mb-3">
<label for="month">Month</label>
<select class="form-control" id="month" name="month">
<option value="">All</option>
<option value="1">January</option>
<option value="2">February</option>
</select>
</div>
<div class="col-md-4 mb-3">
<button type="submit" class="btn btn-primary mt-4">Apply Filter</button>
</div>
</div>
</form>
<!-- Canvas untuk Chart.js -->
<canvas id="salesChart" width="400" height="200"></canvas>
</div>
<!-- Script Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://code.jquery.com/jquery-3.7.1.js"></script>
<script>
var $jq = jQuery.noConflict();
$jq(document).ready(function() {
// Fungsi untuk memuat data grafik dari server
function loadChartData(year, month) {
$jq.ajax({
url: "{{ route('chart.data') }}",
method: 'GET',
data: { year: year, month: month },
success: function(data) {
var ctx = document.getElementById('salesChart').getContext('2d');
// Periksa jika chart sudah ada, lalu hilangkan
if (window.salesChart instanceof Chart) {
window.salesChart.destroy();
}
// Buat chart baru
window.salesChart = new Chart(ctx, {
type: 'bar',
data: {
labels: data.labels, // Bulan
datasets: data.datasets, // Dataset produk
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
},
error: function(jqXHR, textStatus, errorThrown) {
console.error('AJAX error:', textStatus, errorThrown);
}
});
}
// Muat data awal
loadChartData($jq('#year').val(), $jq('#month').val());
// Event listener untuk form filter
$jq('#filter-form').submit(function(e) {
e.preventDefault();
loadChartData($jq('#year').val(), $jq('#month').val());
});
});
</script>
@endsection
Dan buat file layout.blade.php di halaman views dan tambahkan code berikut:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@yield('title', 'CRUD Posts')</title>
<!-- Tambahkan Bootstrap CSS atau styling lainnya -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
<!-- Navbar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="{{ route('posts.index') }}">My Blog</a>
<div class="collapse navbar-collapse">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="{{ route('chart.index') }}">Chart</a>
</li>
</ul>
</div>
</nav>
<!-- Main Content -->
<div class="container mt-5">
@if (session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
@yield('content')
</div>
<!-- Tambahkan Bootstrap JS atau script lainnya -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
</body>
</html>
Langkah 7: Uji Aplikasi
Jalankan server Laravel:
php artisan serve
Akses halaman grafik di browser Anda:
http://localhost:8000/chart
Sekarang Anda akan melihat grafik penjualan yang lebih kompleks dengan fitur multiple datasets untuk beberapa produk, filter berdasarkan bulan dan tahun, serta data yang dimuat secara dinamis menggunakan AJAX.
Jika berhasil step by stepnya, maka akan menghasilkan sebagai berikut: