Program Beasiswa Gratis!

Cara Membuat Struktur Organisasi Dinamis dengan Laravel & jQuery

Struktur organisasi adalah representasi visual yang menunjukkan hierarki dan hubungan antar bagian dalam suatu organisasi. Dengan menggunakan jQuery, kita dapat membuat struktur organisasi yang interaktif dan mudah diubah sesuai kebutuhan, tanpa perlu mengubah kode secara manual. Melalui pendekatan ini, pengguna dapat menambahkan, menghapus, atau memodifikasi elemen-elemen dalam struktur organisasi secara real-time, memberikan fleksibilitas dan efisiensi dalam pengelolaannya. Dalam tutorial ini, kita akan membahas cara membangun struktur organisasi dinamis dengan mengintegrasikan jQuery, serta memberikan contoh implementasi dan penjelasan terkait cara kerja setiap bagian dari kode.

Instalasi Laravel

Langkah pertama adalah menginstal Laravel, sebuah framework PHP yang sangat populer untuk membangun aplikasi web. Instalasi dapat dilakukan menggunakan Composer, manajer dependensi PHP. Pastikan Anda memiliki Composer terinstal di sistem Anda. Gunakan perintah berikut untuk menginstal Laravel:

composer create-project laravel/laravel nama-proyek

Konfigurasi .env

Setelah instalasi Laravel, masuklah ke dalam folder projek kalian menggunakan perintah berikut:

cd “Direktori projek laravel kalian”

langkah berikutnya adalah meng konfigurasi file .env untuk mengatur berbagai variabel lingkungan, seperti koneksi basis data, pengaturan mail, dan pengaturan lainnya. Buka file .env yang ada di root proyek Anda dan sesuaikan pengaturan yang diperlukan, misalnya untuk koneksi ke database MySQL:

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

Membuat File View

Untuk membuat view di Laravel, kamu perlu membuat file Blade yang terletak di direktori resources/views. Blade adalah templating engine yang digunakan oleh Laravel untuk menghasilkan HTML. Misalnya, kita ingin membuat view yang bernama orgchart.blade.php untuk menampilkan struktur organisasi. Lalu isi orgchart.blade.php dengan kodingan berikut

 

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/orgchart/2.1.0/css/jquery.orgchart.min.css">
<style>
        #chart-container {
            position: relative;
            display: flex;
            justify-content: center;
            align-items: center;
        }
    </style>
<div id="chart-container"></div>  
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/orgchart/2.1.0/js/jquery.orgchart.min.js"></script>
<script>
  //Disini kita akan memprogram struktur organisasi
</script>

Tidak lupa juga kita akan mendeklarasikan route untuk view yang sudah kita buat dengan membuka file routes/web.php lalu masukkan kode berikut:

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

Membuat Migration dan Model

Untuk menyimpan data struktur organisasi, buatlah migration untuk tabel yang akan digunakan, misalnya tabel user_structure. Gunakan perintah artisan untuk membuat migration dan model secara bersamaan:

php artisan make:model UserStructure -m

Kemudian akan terbuat file baru di dalam app\Models dan database\Migration,
buka file migration yang telah dibuat di dalam database\Migration, dan tuliskan kode berikut:

 

<?php


use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;


return new class extends Migration
{
    public function up(): void
    {
        Schema::create('user_structures', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->references('id')->on('users');
            $table->foreignId('user_report_id')->references('id')->on('users');
            $table->text('description')->nullable();
            $table->timestamps();
        });
    }


    public function down(): void
    {
        Schema::dropIfExists('user_structures');
    }
};

lalu buka UserStructure yang ada di dalam app\Models dan buat seperti berikut:

<?php


namespace App\Models;


use Illuminate\Database\Eloquent\Model;


class UserStructure extends Model
{
    protected $fillable = ['user_id', 'user_report_id', 'description'];


    public function user()
    {
        return $this->belongsTo(User::class, 'user_id');
    }


    public function report()
    {
        return $this->belongsTo(User::class, 'user_report_id');
    }
}

Jalankan Migration

Untuk membuat table baru di dalam database kita hanya perlu menajalankan perintah php artisan migrate

Membuat crud user

Untuk membuat crud hal yang perlu kita lakukan adalah membuat komponen view, controller dan route. Supaya mempermudah kita berpindah halaman mari buat layout, buatkan file app.blade.php di dalam folder resource/views/layouts seperti berikut:

Pada app.blade.php berisi kode seperti berikut :

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ config('app.name', 'Laravel') }}</title>
   
    <!-- Link to Bootstrap (optional, but often used) -->
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">


    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">


    <!-- Optionally add custom stylesheets -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">


    @stack('styles') <!-- Optional section for adding additional styles -->
</head>
<body>
    <!-- Navbar -->
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
        <div class="container-fluid">
            <a class="navbar-brand" href="{{ url('/') }}">{{ config('app.name', 'Laravel') }}</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarNav">
                <ul class="navbar-nav">
                    <li class="nav-item">
                        <a class="nav-link {{ request()->is('users') ? 'active' : '' }}" href="{{ route('users.index') }}">Pengguna</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link {{ request()->is('users') ? 'active' : '' }}" href="{{ route('organisasi.index') }}">Organisasi</a>
                    </li>
                </ul>
            </div>
        </div>
    </nav>


    <!-- Main Content -->
    <div class="container mt-4">
        @yield('content')
    </div>


    <!-- Optional: Footer -->
    <footer class="bg-light text-center py-3 mt-5">
        <p>&copy; {{ date('Y') }} {{ config('app.name', 'Laravel') }}. All rights reserved.</p>
    </footer>


    <!-- Scripts -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
    @stack('scripts') <!-- Optional section for adding custom scripts -->
</body>
</html>

lalu mari kita buat beberapa view antara lain index, create, edit. buatlah folder users di dalam resource\views, lalu letakkan view di dalam folder tersebut :

Buat view yang sesuai dengan fungsinnya, saya akan membuatnya seperti berikut:

index.blade.php

@extends('layouts.app')


@section('content')
<div class="container">
    <h1>Daftar Pengguna</h1>
    <a href="{{ route('users.create') }}" class="btn btn-primary">Buat Pengguna Baru</a>


    @if(session('success'))
        <div class="alert alert-success">
            {{ session('success') }}
        </div>
    @endif


    <table class="table mt-3">
        <thead>
            <tr>
                <th>ID</th>
                <th>Nama</th>
                <th>Email</th>
                <th>Terverifikasi</th>
                <th>Action</th>
            </tr>
        </thead>
        <tbody>
            @foreach ($users as $user)
                <tr>
                    <td>{{ $user->id }}</td>
                    <td>{{ $user->name }}</td>
                    <td>{{ $user->email }}</td>
                    <td>{{ $user->email_verified_at ? 'Terverifikasi' : 'Belum Terverifikasi' }}</td>
                    <td>
                        <a href="{{ route('users.edit', $user->id) }}" class="btn btn-warning">Edit</a>
                        <form action="{{ route('users.destroy', $user->id) }}" method="POST" style="display:inline;">
                            @csrf
                            @method('DELETE')
                            <button type="submit" class="btn btn-danger" onclick="return confirm('Apakah Anda yakin ingin menghapus pengguna ini?')">Hapus</button>
                        </form>
                    </td>
                </tr>
            @endforeach
        </tbody>
    </table>
</div>
@endsection

create.blade.php

@extends('layouts.app')


@section('content')
<div class="container">
    <h1>Buat Pengguna Baru</h1>
   
    <form action="{{ route('users.store') }}" method="POST">
        @csrf
        <div class="mb-3">
            <label for="name" class="form-label">Nama</label>
            <input type="text" class="form-control" id="name" name="name" required>
        </div>
       
        <div class="mb-3">
            <label for="email" class="form-label">Email</label>
            <input type="email" class="form-control" id="email" name="email" required>
        </div>


        <div class="mb-3">
            <label for="password" class="form-label">Kata Sandi</label>
            <input type="password" class="form-control" id="password" name="password" required>
        </div>


        <div class="mb-3">
            <button type="submit" class="btn btn-success">Simpan</button>
        </div>
    </form>
</div>
@endsection

edit.blade.php

@extends('layouts.app')


@section('content')
<div class="container">
    <h1>Edit Pengguna</h1>
   
    <form action="{{ route('users.update', $user->id) }}" method="POST">
        @csrf
        @method('PUT') <!-- Ini untuk menentukan bahwa kita akan menggunakan metode PUT untuk update -->
       
        <div class="mb-3">
            <label for="name" class="form-label">Nama</label>
            <input type="text" class="form-control" id="name" name="name" value="{{ old('name', $user->name) }}" required>
        </div>


        <div class="mb-3">
            <label for="email" class="form-label">Email</label>
            <input type="email" class="form-control" id="email" name="email" value="{{ old('email', $user->email) }}" required>
        </div>


        <div class="mb-3">
            <label for="password" class="form-label">Kata Sandi</label>
            <input type="password" class="form-control" id="password" name="password">
            <small class="text-muted">Biarkan kosong jika tidak ingin mengubah kata sandi</small>
        </div>


        <div class="mb-3">
            <button type="submit" class="btn btn-warning">Update</button>
        </div>
    </form>
</div>
@endsection

Jika sudah, mari buat controller dengan cara menjalankan perintah berikut php artisan make:controller UserController

lalu kita buat beberapa fungsi yang akan mengatur semua proses crud user : 

<?php


namespace App\Http\Controllers;


use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;


class UserController extends Controller
{
    // Menampilkan daftar pengguna
    public function index()
    {
        $users = User::all();
        return view('users.index', compact('users'));
    }


    // Menampilkan form untuk membuat pengguna baru
    public function create()
    {
        return view('users.create');
    }


    // Menyimpan pengguna baru
    public function store(Request $request)
    {
        $request->validate([
            'name' => 'required',
            'email' => 'required',
            'password' => 'required',
        ]);


        // Menyimpan pengguna baru, dengan email_verified_at diisi otomatis
        $user = new User();
        $user->name = $request->name;
        $user->email = $request->email;
        $user->password = Hash::make($request->password);
        $user->email_verified_at = now(); // Mengisi email_verified_at otomatis
        $user->save();


        return redirect()->route('users.index')->with('success', 'Pengguna berhasil dibuat');
    }


    // Menampilkan form untuk mengedit pengguna
    public function edit(User $user)
    {
        return view('users.edit', compact('user'));
    }


    // Mengupdate data pengguna
    public function update(Request $request, User $user)
    {
        $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users,email,' . $user->id,
            'password' => 'nullable|string|min:8|confirmed',
        ]);


        // Update data pengguna
        $user->name = $request->name;
        $user->email = $request->email;
        if ($request->password) {
            $user->password = Hash::make($request->password);
        }
        $user->email_verified_at = now(); // Mengisi email_verified_at otomatis
        $user->save();


        return redirect()->route('users.index')->with('success', 'Pengguna berhasil diperbarui');
    }


    // Fungsi untuk menghapus data pengguna
    public function destroy(User $user)
    {
        // Menghapus pengguna dari database
        $user->delete();


        // Redirect ke halaman daftar pengguna dengan pesan sukses
        return redirect()->route('users.index')->with('success', 'Pengguna berhasil dihapus');
    }
}

Terakhir, kita akan mendeklarasikan route untuk user dengan cara memasukkan kode berikut di dalam routes\web.php :

use App\Http\Controllers\UserController;


Route::resource('users', UserController::class);

Membuat crud struktur organisasi

Sama seperti sebelumnya kita akan membuat beberapa view antara lain index, create, edit pada folder resource\views\organisasi

index.blade.php

@extends('layouts.app')


@section('content')
<div class="container">
    <h1>Daftar Struktur Organisasi</h1>


    @if(session('success'))
        <div class="alert alert-success">
            {{ session('success') }}
        </div>
    @endif


    <a href="{{ route('organisasi.create') }}" class="btn btn-primary mb-3">Tambah Struktur Organisasi</a>


    <table class="table">
        <thead>
            <tr>
                <th>ID</th>
                <th>Nama Pengguna</th>
                <th>Nama Atasan</th>
                <th>Deskripsi</th>
                <th>Aksi</th>
            </tr>
        </thead>
        <tbody>
            @foreach($userStructures as $structure)
                <tr>
                    <td>{{ $structure->id }}</td>
                    <td>{{ $structure->user->name }}</td>
                    <td>{{ $structure->userReport->name }}</td>
                    <td>{{ $structure->description }}</td>
                    <td>
                        <a href="{{ route('organisasi.edit', $structure->id) }}" class="btn btn-warning">Edit</a>
                        <form action="{{ route('organisasi.destroy', $structure->id) }}" method="POST" style="display:inline;">
                            @csrf
                            @method('DELETE')
                            <button type="submit" class="btn btn-danger" onclick="return confirm('Apakah Anda yakin ingin menghapus struktur organisasi ini?')">Hapus</button>
                        </form>
                    </td>
                </tr>
            @endforeach
        </tbody>
    </table>
</div>
@endsection

create.blade.php

@extends('layouts.app')


@section('content')
<div class="container">
    <h1>Tambah Struktur Organisasi</h1>


    @if(session('success'))
        <div class="alert alert-success">
            {{ session('success') }}
        </div>
    @endif


    <form action="{{ route('organisasi.store') }}" method="POST">
        @csrf
        <div class="mb-3">
            <label for="user_id" class="form-label">Pilih Pengguna</label>
            <select name="user_id" id="user_id" class="form-control @error('user_id') is-invalid @enderror">
                <option value="">Pilih Pengguna</option>
                @foreach($users as $user)
                    <option value="{{ $user->id }}" {{ old('user_id') == $user->id ? 'selected' : '' }}>{{ $user->name }}</option>
                @endforeach
            </select>
            @error('user_id')
                <div class="invalid-feedback">{{ $message }}</div>
            @enderror
        </div>


        <div class="mb-3">
            <label for="user_report_id" class="form-label">Pilih Atasan</label>
            <select name="user_report_id" id="user_report_id" class="form-control @error('user_report_id') is-invalid @enderror">
                <option value="">Pilih Atasan</option>
                @foreach($users as $user)
                    <option value="{{ $user->id }}" {{ old('user_report_id') == $user->id ? 'selected' : '' }}>{{ $user->name }}</option>
                @endforeach
            </select>
            @error('user_report_id')
                <div class="invalid-feedback">{{ $message }}</div>
            @enderror
        </div>


        <div class="mb-3">
            <label for="description" class="form-label">Deskripsi</label>
            <textarea name="description" id="description" class="form-control @error('description') is-invalid @enderror">{{ old('description') }}</textarea>
            @error('description')
                <div class="invalid-feedback">{{ $message }}</div>
            @enderror
        </div>


        <button type="submit" class="btn btn-primary">Simpan</button>
    </form>
</div>
@endsection

edit.blade.php

@extends('layouts.app')


@section('content')
<div class="container">
    <h1>Edit Struktur Organisasi</h1>


    @if(session('success'))
        <div class="alert alert-success">
            {{ session('success') }}
        </div>
    @endif


    <form action="{{ route('organisasi.update', $userStructure->id) }}" method="POST">
        @csrf
        @method('PUT')


        <div class="mb-3">
            <label for="user_id" class="form-label">Pilih Pengguna</label>
            <select name="user_id" id="user_id" class="form-control @error('user_id') is-invalid @enderror">
                <option value="">Pilih Pengguna</option>
                @foreach($users as $user)
                    <option value="{{ $user->id }}" {{ old('user_id', $userStructure->user_id) == $user->id ? 'selected' : '' }}>{{ $user->name }}</option>
                @endforeach
            </select>
            @error('user_id')
                <div class="invalid-feedback">{{ $message }}</div>
            @enderror
        </div>


        <div class="mb-3">
            <label for="user_report_id" class="form-label">Pilih Atasan</label>
            <select name="user_report_id" id="user_report_id" class="form-control @error('user_report_id') is-invalid @enderror">
                <option value="">Pilih Atasan</option>
                @foreach($users as $user)
                    <option value="{{ $user->id }}" {{ old('user_report_id', $userStructure->user_report_id) == $user->id ? 'selected' : '' }}>{{ $user->name }}</option>
                @endforeach
            </select>
            @error('user_report_id')
                <div class="invalid-feedback">{{ $message }}</div>
            @enderror
        </div>


        <div class="mb-3">
            <label for="description" class="form-label">Deskripsi</label>
            <textarea name="description" id="description" class="form-control @error('description') is-invalid @enderror">{{ old('description', $userStructure->description) }}</textarea>
            @error('description')
                <div class="invalid-feedback">{{ $message }}</div>
            @enderror
        </div>


        <button type="submit" class="btn btn-primary">Simpan Perubahan</button>
    </form>
</div>
@endsection

buat controller dengan menjalankan perintah berikut php artisan make:controller OrganisasiController

<?php


namespace App\Http\Controllers;


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


class OrganisasiController extends Controller
{
    // Menampilkan form pembuatan struktur organisasi
    public function create()
    {
        $users = User::all(); // Ambil semua pengguna untuk pilihan
        return view('organisasi.create', compact('users'));
    }


    // Menyimpan data struktur organisasi
    public function store(Request $request)
    {
        $request->validate([
            'user_id' => 'required|exists:users,id',
            'user_report_id' => 'required|exists:users,id',
            'description' => 'nullable|string',
        ]);


        UserStructure::create([
            'user_id' => $request->user_id,
            'user_report_id' => $request->user_report_id,
            'description' => $request->description,
        ]);


        return redirect()->route('organisasi.index')->with('success', 'Struktur Organisasi berhasil dibuat!');
    }


    // Menampilkan daftar struktur organisasi
    public function index()
    {
        $userStructures = UserStructure::with('user', 'userReport')->get();
        return view('organisasi.index', compact('userStructures'));
    }


    // Menampilkan form edit untuk struktur organisasi
    public function edit(UserStructure $userStructure)
    {
        $users = User::all(); // Ambil semua pengguna untuk dropdown
        return view('organisasi.edit', compact('userStructure', 'users'));
    }


    // Menyimpan perubahan pada struktur organisasi
    public function update(Request $request, UserStructure $userStructure)
    {
        $request->validate([
            'user_id' => 'required|exists:users,id',
            'user_report_id' => 'required|exists:users,id',
            'description' => 'nullable|string',
        ]);


        // Update data
        $userStructure->update([
            'user_id' => $request->user_id,
            'user_report_id' => $request->user_report_id,
            'description' => $request->description,
        ]);


        return redirect()->route('organisasi.index')->with('success', 'Struktur Organisasi berhasil diperbarui!');
    }


    // Menghapus struktur organisasi
    public function destroy(int $id)
    {
        $userStructure = UserStructure::findOrFail($id);
        $userStructure->delete();
        return redirect()->route('organisasi.index')->with('success', 'Struktur Organisasi berhasil dihapus!');
    }
}

Deklarasikan route untuk class OrganisasiController

Route::resource('organisasi', OrganisasiController::class);

Membuat API struktur organisasi

Untuk membuat chart struktur organisasi kita agar dinamis, kita perlu membuat api. dengan cara membuat Controller API yang outputnnya adalah struktur JSON dari API tersebut.

php artisan make:controller OrganisasiApiController
<?php


namespace App\Http\Controllers;


use App\Models\User;
use Illuminate\Http\Request;
use App\Models\UserStructure;
use Illuminate\Support\Facades\DB;


class OrganisasiApiController extends Controller
{
    public function getData()
    {
        return $this->getHierarchy();
    }


    public function getHierarchy()
    {
        $organizations = UserStructure::all();


        $ceo = DB::select('select * from user_structures where user_id = user_report_id');


        if($ceo == null){
            return;
        }


        $hierarchy = $this->buildHierarchy($organizations, $ceo[0]->user_id);
        $ceoName = User::where('id',$ceo[0]->user_id)->first();


        return [
            "name"=>$ceoName->name,
            "title"=>$ceo[0]->description,
            "children"=>$hierarchy
        ];
    }


    private function buildHierarchy($organizations, $parentId)
    {
        $grouped = $organizations->groupBy('user_report_id');


        if(!isset($grouped[$parentId])){
            return [];
        }


        return $grouped[$parentId]->map(function($organization) use ($grouped,$parentId){
            if($organization->user_id == $parentId){
                return;
            }
            $user = User::where('id',$organization->user_id)->first();
            return [
                "name" => $user->name,
                "title" => $organization->description,
                "children"=>$this->buildHierarchy($grouped->flatten(), $organization->user_id)
            ];
        });
    }
}

Jangan lupa deklarasikan route tersebut.

Route::get('api/organisasi',[OrganisasiApiController::class, 'getData']);

Menyambungkan api dengan chart js

Langkah terakhir kita hanya perlu menyambungkan api kita dengan kode chart untuk memvisualisasikan data yang telah kita buat dengan cara, buka file orgchart.blade.php yang terletak pada resource\views.

$(function() {
        $.ajax({
            url: 'http://localhost:8000/api/organisasi', // merupakan url api yang telah dibuat
            method: 'GET',
            dataType: 'json',
            success: function(data) {
                cleanData(data);
                $('#chart-container').orgchart({
                    'data': data,
                    'nodeContent': 'title',
                    'pan': true,
                    'zoom': true
                });
            },
            error: function(jqXHR, textStatus, errorThrown) {
                console.error('Error:', textStatus, errorThrown);
            }
        });
    });
    function cleanData(node) {
        if (!node.children) {
            node.children = [];
        }
        node.children = node.children.filter(child => child !== null);
        node.children.forEach(child => cleanData(child));
    }

Berikut output dari code diatas dengan struktur ini akan berubah jika kita mengubah data yang ada, atau dengan kata lain struktur organisasi ini dinamis.

 

Author :

Muhammad Farrel Arrahman – Backend developer
Tentang saya, Saya adalah salah satu murid di SMKN 1 Tanjungpandan yang memiliki ambisi untuk menjadi seorang professional backend programer. Oleh karna itu saya sangat senang mempelajari hal hal baru terutama tentang program.

Table of Contents

Related Posts

Tulis Pesan
💬 Butuh bantuan?
Scan the code
SMKDEV by Eudeka
Halo 👋
Apa yang bisa kami bantu?