Badr Interactive Engineering
Berbagi pengalaman untuk menciptakan software yang lebih baik

Membuat Active Menu dengan View Composer di Laravel

Dalam sebuah aplikasi web, biasanya yang bertipe web admin, umum kita jumpai sidebar berisi menu-menu. Daftar menu tersebut biasanya memiliki state active atau biasa alias tidak aktif, menunjukkan si user sedang berada di halaman apa. Berbagai template web admin biasanya sudah mempunyai styling sendiri seperti contoh di bawah ini:

template-1 template-2

Di atas adalah template favorit anak Badr, yaitu SB-Admin dan AdminLTE, sebagai contoh styling active menu. Biasanya, style tersebut didapat dengan menambahkan CSS class .active pada elemen menu item atau butir navigasi. Secara back-end, kita harus memastikan ketika view tersebut mau dilukis alias render, mana menu item yang harus diberi class .active.

Di Laravel, biasanya kita mengirim data atau variabel yang dibutuhkan View dari fungsi yang ada di Controller. Masalahnya, data menu yang aktif itu kita butuhkan untuk setiap halaman yang diminta. Solusi naifnya, ya kita mesti ngirim paramater seperti active_menu => 'dashboard' pada setiap fungsi yang ada. Nah, ada beberapa cara lain yang lebih cerdas untuk ini, salah satunya dengan View Composer.

Konsep

View Composer ialah sebuah callback pada Laravel yang dipanggil ketika sebuah view akan dilukis (render)1. Nah, fitur ini dapat kita gunakan untuk berbagi data yang sama pada beberapa view. So, kita akan membuat composer untuk view yang memuat sidebar menu tersebut dan mengirim data menu mana yang sekarang lagi diakses.

Masalah berikutnya, darimana kita tahu menu yang lagi diakses? paling gampang sih dari pengecekan route alias rute yang lagi diakses. Misal site.com/users biasanya jadi prefix untuk semua halaman yang berkaitan dengan user. Tapi ada cara lain yang lebih asik nih, mau tau gak? yuk lanjutin bacanya :D

Langkah-langkah

  1. Buat class ActiveMenuComposer.php seperti contoh di bawah. Oya, berkas class ini bisa ditaruh di direktori mana aja, yang penting namespace-nya bener. Dalam contoh ini berkas ditaruh di app/Http/Composer/.

     <?php
     namespace App\Http\Composer;
    
     use View;
     use Illuminate\Http\Request;
    
     class ActiveMenuComposer
     {
         protected $request;
    
         /**
          * ActiveMenuComposer constructor.
          * @param Request $request
          */
         public function __construct(Request $request)
         {
             $this->request = $request;
         }
    
         public function compose(View $view)
         {
    
         }
     }
    
  2. Selanjutnya, kita kaitkan informasi menu yang aktif dengan rute aplikasi di app/Http/routes.php sebagai berikut:

     Route::group(['prefix' => 'users', 'active_menu' => 'user'], function() {
             //user related area
             Route::get('{id}', 'UserController@detail');
             Route::get('{id}/edit', 'UserController@editForm');
             Route::post('{id}/edit', 'UserController@editSave');
         }
     );
    

    Contoh pembuatan rute di atas memanfaatkan custom route parameter yang akan dikirim sebagai atribut dalam objek Illuminate\Routing\Route. Nah, objek Route tersebut bisa didapat dari instance Illuminate\Http\Request yang sudah kita inject alias masukkan di constructor view composer di langkah sebelumnya.2

  3. Tambahkan parameter active menu di view sesuai dengan route parameter yang tadi didefinisikan.

     public function compose(View $view)
     {
         $routeAction = $this->request->route()->getAction();
    
         if (array_key_exists('active_menu', $routeAction)) {
             $view->with('active_menu', $routeAction['active_menu']);
         } else {
             $view->with('active_menu', 'default');
         }
     }
    

    Fungsi getAction() pada objek Route akan mengembalikan array berisi route parameter yang kita definisikan tadi3. Isinya lebih banyak dari yang kita tulis sih, tapi yang kita cek cuma yang kita bikin aja yaitu active_menu.

  4. Jangan lupa daftarkan view composer kita untuk view yang terkait di sebuah Service Provider. Kita bisa buat provider khusus untuk mendaftarkan view composer, atau gunakan saja app\Providers\AppServiceProvider.php. Yang penting isi fungsi boot() seperti berikut:

     public function boot()
     {
         view()->composer('layouts.admin.sidebar', 'App\Http\Composer\ActiveMenuComposer');
     }
    

    Kode di atas mendaftarkan view composer ActiveMenuComposer yang kita buat untuk view layouts.admin.sidebar yang memuat sidebar menu. View-nya silakan sesuaikan aja.

  5. Ambil data active_menu yang sudah ditambahkan oleh view composer. Di view layouts.admin.sidebar, kita dapat mengaksesnya seperti biasa, contohnya seperti ini:

     <li class="{{ $active_menu == 'user' ? 'active' : '' }}">
         <a href="{{ url('admin/users') }}">
             <i class="fa fa-users"></i> <span>Anggota</span>
         </a>
     </li>
    

Selesai!

Suplemen

  • Satu view composer bisa digunakan untuk banyak view. Parameter pertama ketika mendaftarkannya diubah jadi array:

      view()->composer(['layouts.admin.sidebar', 'layouts.admin.header'],
          'App\Http\Composer\ActiveMenuComposer');
    
  • Atau bisa juga pakai wildcard (*):

      view()->composer(['layouts.master.sidebar', 'layouts.admin.*'],
          'App\Http\Composer\ActiveMenuComposer');
    
  • Contoh di atas sudah dicoba di Laravel 5.2 dan berjalan baik. Menurut laman dokumentasinya4, hal yang sama dapat dilakukan di versi 5.1 juga. Untuk versi 5.0, cara mendaftarkan view composer-nya sedikit berbeda:

      //mendaftar satu composer
      View::composer('layouts.admin.sidebar', 'App\Http\Composer\ActiveMenuComposer');
      //mendaftar banyak composer
      View::composers([
          'App\Http\ViewComposers\AdminComposer' => ['admin.index', 'admin.profile'],
          'App\Http\ViewComposers\UserComposer' => 'user',
          'App\Http\ViewComposers\ProductComposer' => 'product'
      ]);
    

Penutup

Seperti class Controller di dalam Laravel, kita juga bisa mengguakan Eloquent model dan service lain di dalam view composer. Bisa di-inject melalui constructor ataupun dengan facade. Hal ini berguna jika kita ingin berbagi sebuah data untuk banyak view sekaligus. Misal data daftar kota dan provinsi di database diperlukan di setiap halaman pencarian atau form pendaftaran. Daripada mesti ngambil terus kirim data yang sama di setiap fungsi yang membutuhkan, mending bikin sekali terus daftarin. Beres.

Yak segini dulu dah untuk kali ini. Seperti dibilang di awal, ada banyak cara lain untuk implementasi active menu, googling aja kalau penasaran. Ini juga dapetnya berawal dari gugling, hehe. Nah kalau udah punya metode lain yang mungkin lebih keren, jangan lupa bagi-bagi di sini! :D

Referensi