Laravel 11 Apexcharts Example Tutorial

             ApexCharts is a JavaScript library used for creating beautiful and interactive charts on websites. It makes it easy to visualize data through various chart types like bar, line, pie, and more. Users can customize the appearance, animate the charts, and interact with them to explore data. ApexCharts is popular because it's easy to use and helps make data look appealing and understandable.

Laravel 11 ApexCharts: Create Dynamic Charts with Filter Options in ApexCharts

Table Of Content

1 Prerequisites

1.) PHP version of >= 8.2
2.) Composer
3.) Mysql

2 Introduction

In this example, we will create some dummy user records and then display a Line chart with all months of the current year. So let's follow the below steps and add a chart to your Laravel 11 apps.

3 Create / Install a Laravel Project

3.1 Install Laravel Project

First, ensure Composer is installed on your system. Use the following command to install a new Laravel Project:

composer create-project laravel/laravel laravel11-chart-app

Navigate to your project directory:

cd laravel11-chart-app

3.2 Configure MySql Database

Open the .env file and input the necessary database credentials:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=charts
DB_USERNAME=root
DB_PASSWORD=

4 Create Migration

Next, create a migration for the posts table using the Laravel artisan command:

    php artisan make:migration create_users_table

In the migration file located at database/migrations, add the following code to define the posts table structure:
    
<?php
se Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });

        Schema::create('password_reset_tokens', function (Blueprint $table) {
            $table->string('email')->primary();
            $table->string('token');
            $table->timestamp('created_at')->nullable();
        });

        Schema::create('sessions', function (Blueprint $table) {
            $table->string('id')->primary();
            $table->foreignId('user_id')->nullable()->index();
            $table->string('ip_address', 45)->nullable();
            $table->text('user_agent')->nullable();
            $table->longText('payload');
            $table->integer('last_activity')->index();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('users');
        Schema::dropIfExists('password_reset_tokens');
        Schema::dropIfExists('sessions');
    }
};


Run the migration:

php artisan migrate

5 Create Model

Now, create the User model for the posts table. Create the file at app/Models/User.php and add the following code:
    
<?php
namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    /** @use HasFactory<\Database\Factories\UserFactory> */
    use HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var list
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var list
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * Get the attributes that should be cast.
     *
     * @return array
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
        ];
    }
}


6 Create Factory Class

Generate a factory class to create dummy data that create dynamic chart:

php artisan make:factory UserFactory

Update the database/factories/UserFactory .php with:
    
<?php
namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Illuminate\Support\Carbon;


/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
 */
class UserFactory extends Factory
{
    /**
     * The current password being used by the factory.
     */
    protected static ?string $password;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition(): array
    {
        return [
            'name' => fake()->name(),
            'email' => fake()->unique()->safeEmail(),
            'email_verified_at' => now(),
            'password' => static::$password ??= Hash::make('password'),
            'remember_token' => Str::random(10),
            'created_at'  =>    Carbon::createFromTimestamp(fake()->unixTime()),
        ];
    }

    /**
     * Indicate that the model's email address should be unverified.
     */
    public function unverified(): static
    {
        return $this->state(fn (array $attributes) => [
            'email_verified_at' => null,
        ]);
    }
}

To generate 100 dummy records, use:

php artisan tinker


User::factory()->count(100)->create()

7 Create Controller (UserController)

Create a controller to handle the data loading functionality:

php artisan make:controller UserController

In UserController.php, create an index and filterData function to create dynamic chart:

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\User;

class UserController extends Controller
{
    public function index(Request $request)
    {
        $charts_data = User::selectRaw('count(id) AS data,MONTH(created_at) AS month')->whereYear('created_at',"2024")->groupBy('month')->get();
       
        $chart_data=array();
        foreach($charts_data as $chart)
            {
                $temp=array();
                $temp['x']='2024-'.$chart['month'];
                $temp['y']=$chart['data'];
                $chart_data[]=$temp;
            }
         $charts=$chart_data;   
        return view('index', compact('charts'));
    }
    function filterData(Request $request)
   {

   $year=$request->input('year');
    $charts=User::selectRaw('count(id) AS data,MONTH(created_at) AS month')->whereYear('created_at',$year)->groupBy('month')->get();
   
    $chart_data=array();
    foreach($charts as $chart)
        {
            $temp=array();
            $temp['x']=$year.'-'.$chart['month'];
            $temp['y']=$chart['data'];
            $chart_data[]=$temp;
        }
        $data['charts']=$chart_data;
        return $data;
   }
}
?>

8 Create view (Blade)

In the resources/viewsdirectory, create index.blade.php for the main view:
    
   <!DOCTYPE html>
<html>
<head>
    <title>ApexChat with Filter in Laravel 11 : A Step-by-Step Tutorial - getsamplecode.com</title>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.0.1/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdn.datatables.net/1.11.4/css/dataTables.bootstrap5.min.css" rel="stylesheet">
    <script src="https://code.jquery.com/jquery-3.5.1.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
    <style>
  .showLeft {
  background-color: white !important;
  border: 1px solid white !important;
  text-shadow: white !important;
  color: black !important;
  padding: 10px;
}
.icons li {
  background: none repeat scroll 0 0 black;
  height: 7px;
  width: 7px;
  line-height: 0;
  list-style: none outside none;
  margin-right: 15px;
  margin-top: 3px;
  vertical-align: top;
  border-radius: 50%;
  pointer-events: none;
}
.btn-left {
  left: 0.4em;
}
.btn-right {
  right: 0.4em;
}
.btn-left,
.btn-right {
  position: absolute;
  top: 0.24em;
}
.dropbtn {
  background-color: #4caf50;
  position: fixed;
  color: white;
  font-size: 16px;
  border: none;
  cursor: pointer;
}
.dropbtn:hover,
.dropbtn:focus {
  background-color: #3e8e41;
}
.dropdown {
  position: absolute;
  display: inline-block;
  right: 0.4em;
}
.dropdown-content {
  display: none;
  position: relative;
  margin-top: 60px;
  background-color: #f9f9f9;
  min-width: 160px;
  overflow: auto;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  z-index: 1;
}

.dropdown-content a {
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}

.dropdown a:hover {
  background-color: #f1f1f1;
}

.show {
  display: block;
}

</style>

</head>
<body>
       
<div class="container">
      <!-- three dot menu -->
  <div class="dropdown">
    <!-- three dots -->
    <ul class="dropbtn icons btn-right showLeft" onclick="showDropdown()">
      <li></li>
      <li></li>
      <li></li>
    </ul>
    <!-- menu -->
    <div id="myDropdown" class="dropdown-content">
      <a href="javascript:void(0)" class="chart_filter" data-value="2024">This Year</a>
      <a  href="javascript:void(0)" class="chart_filter" data-value="2023">Last Year</a>
    </div>
  </div>
       <div id="chart"></div>
    </div>

       
</body>
       
<script type="text/javascript">
     function showDropdown() {
       document.getElementById("myDropdown").classList.toggle("show");
     }
     
     // Close the dropdown if the user clicks outside of it
     window.onclick = function(event) {
       if (!event.target.matches(".dropbtn")) {
         var dropdowns = document.getElementsByClassName("dropdown-content");
         var i;
         for (i = 0; i < dropdowns.length; i++) {
           var openDropdown = dropdowns[i];
           if (openDropdown.classList.contains("show")) {
             openDropdown.classList.remove("show");
           }
         }
       }
     };
     
             $(document).ready(function() {
               
                 var options = {
               series: [{
               name: 'Profile Created',
               data: [44, 55, 41, 67, 22, 43]
             }],
               chart: {
               type: 'bar',
               height: 350,
               stacked: true,
               toolbar: {
                 show: true
               },
               zoom: {
                 enabled: true
               }
             },
             responsive: [{
               breakpoint: 480,
               options: {
                 legend: {
                   position: 'bottom',
                   offsetX: -10,
                   offsetY: 0
                 }
               }
             }],
             plotOptions: {
               bar: {
                 horizontal: false,
                 borderRadius: 10,
                 borderRadiusApplication: 'end', // 'around', 'end'
                 borderRadiusWhenStacked: 'last', // 'all', 'last'
                 dataLabels: {
                   total: {
                     enabled: true,
                     style: {
                       fontSize: '13px',
                       fontWeight: 900
                     }
                   }
                 }
               },
             },
             xaxis: {
               type: 'datetime',
               categories: ['01/01/2024 GMT', '01/02/2024 GMT', '01/03/2024 GMT', '01/04/2024 GMT',
                 '01/05/2024 GMT', '01/06/2024 GMT'
               ],
             },
             legend: {
               position: 'right',
               offsetY: 40
             },
             fill: {
               opacity: 1
             }
             };
     
             var chart = new ApexCharts(document.querySelector("#chart"), options);
             chart.render();
             chart.updateSeries([{
                                                     data: <?php echo json_encode($charts);?>
                                                 }]);
     
         $(".chart_filter").on("click", function(){
           
          $.ajax({
                     url: "search",
                     method: 'POST',
                     data: {'year':$(this).data("value"), "_token": "{{ csrf_token() }}",},
                     dataType: 'json',
                     success: function(response) {
                       chart.updateSeries([{
                                                     data: response.charts
                                                 }]);
            
                     }
               });
     
         });
                        
             });
     
            
         
</script>
</html>

    

9 Define Routes

In routes/web.php, define the necessary routes:

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\UserController;


Route::get('/', function () {
    return view('welcome');
});

Route::get('users',[UserController::class,'index'])->name('users.index');
Route::post('search',[UserController::class,'filterData'])->name('users.search');

10 Folder Structure

11 Run Laravel Server to Test the App

Use the following command to serve the Laravel app:

php artisan serve

12 Conclusion

You have successfully created the Dynamic Line Chart in Apexchars using laravel 11

Tags