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>© {{ 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.