Cara Membuat Kategori dan Sub Kategori di Laravel + Vue.js

wahyunanangwidodo

wahyunanangwidodo Rabu, 13 Januari 2021

Cara Membuat Kategori dan Sub Kategori di Laravel + Vue.js

Laravel memberikan kemudahan untuk kita membangun relationship atau menghubungkan antar tabel mysql dalam query data.

Seperti suatu data yang ingin kita bagi atau di filter sesuai keyword tertentu yang diambil dari data lain pada tabel di database.

Contohnya tabel khusus seperti tabel "Kategori" yang dihubungkan dengan tabel lain yang menjadi data induk untuk mengategorikan suatu data. 

Di Laravel sangat mudah untuk kita buat relasi antar tabel, dan bahkan relasi antar baris data pada tabel itu sendiri. Contohnya seperti yang akan dibuat pada tutorial ini.

Kita akan membuat Kategori dan Sub Kategori dengan membangun relasi antar baris (row) dari suatu tabel yaitu "Kategori".

Lihat Demo

Instalasi Laravel

Kita mulai dengan melakukan instalasi laravel, membuat database baru dan menghubungkannya.

~ laravel new blog
#atau
~ composer create-project --prefer-dist laravel/laravel blog
//.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=db_blog
DB_USERNAME=root
DB_PASSWORD=

Membuat Tabel

Selanjutnya kita buat Model baru sekaligus kontroller dan file migrasi baru untuk membuat tabel kategori.

php artisan make:model Category -mc
//..create_categories_tabel.php
public function up()
{
  Schema::create('categories', function (Blueprint $table) {
     $table->id();
     $table->unsignedInteger('parent_id')->nullable();
     $table->string('name');
     $table->timestamps();
  });
}

Setelah itu kita jalankan perintah migrasi.

php artisan migrate

Kita tambahkan 2 field name dan parent_id untuk tabel categories. parent_id kita gunakan untuk menyimpan id dari kategori lain yang dijadikan induk / parent.

Membuat Request

Sekarang kita buka CategoryController.php dan membuat request insert data untuk kategori baru.

<?php

namespace App\Http\Controllers;

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

class CategoryController extends Controller
{  
    public function create(Request $request){

        $category = new Category;

        $category->name = $request->name;
        $category->parent_id = $request->parent_id; 
    
        $category->save(); 
    
        return response()->json($category, 200);
    }
}

Setelah itu kita buat route di routes/api.php.

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

use App\Http\Controllers\CategoryController;
 
Route::post('category/create', [CategoryController::class, 'create']);

Selanjutnya kita coba untuk insert data atau membuat kategori baru melalui postman.

Cara Membuat Kategori dan Sub Kategori di Laravel + Vue.js

Dari gambar diatas telah berhasil melakukan insert data baru. Jika dilihat, kita dapat mengkosongkan value untuk parent_id atau null, dimana data ini dapat digunakan sebagai parent atau induk dari sub kategori.

Sekarang kita coba kembali untuk insert data kategori baru dengan menambahkan id parent yang kita ambil dari kategori yang dibuat sebelumnya seperti dibawah ini.

Cara Membuat Kategori dan Sub Kategori di Laravel + Vue.js

Membuat Relasi dan Kueri

Setelah memiliki data di database, selenjutnya kita membuat relasi model dan kueri data.

Kita buka Models/Category.php dan buat seperti dibawah ini.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    use HasFactory;

    public function children() 
    {
        return $this->hasMany(Category::class, 'parent_id');
    }
}

Kemudian buka CategoryController.php dan tambahkan method baru seperti dibawah ini

public function allCategories()
{
   $categories = Category::with('children')->whereNull('parent_id')->get();
      
   return response()->json($categories, 200);
} 

Tambahkan juga route baru.

//api.php
Route::get('category/allCategories', [CategoryController::class, 'allCategories']);

Hasilnya seperti berikut.

GET : http://localhost:8000/api/category/allCategories

[
    {
        "id": 1,
        "parent_id": null,
        "name": "Tutorials",
        "created_at": "2021-01-10T15:11:41.000000Z",
        "updated_at": "2021-01-10T15:11:41.000000Z",
        "children": [
            {
                "id": 2,
                "parent_id": 1,
                "name": "Laravel",
                "created_at": "2021-01-10T15:25:40.000000Z",
                "updated_at": "2021-01-10T15:25:40.000000Z"
            }
        ]
    }
]

Instalasi Vue dan Bootstrap

Setelah membuat request api insert data melalui postman, selanjutnya kita membuat bagian frontend menggunakan vue.js dan css bootstrap.

Kita install terlebih dahulu library yang dibutuhkan.

npm install
npm install vue vue-template-compiler --save-dev
npm install bootstrap jquery popper.js sass sass-loader --save-dev

Kemudian kita buat instance vue dan pengaturan bootstrap.

Kita buat instance vue terlebih dahulu. Silahkan buka resources/js/app.js dan buat seperti dibawah ini.

//app.js
require('./bootstrap');

window.Vue = require('vue');

import App from './components/App'

const app = new Vue({
  el: '#app',
  components: { App }, 
});

Buat folder components di resources/js dan tambahkan file baru dengan nama App.vue.

//App.vue
 <template>
  <div>
   <h1>Hello World!</h1>
  </div>
</template>

Lalu buka Routes/web.php dan ubah route yang ada dengan dibawah ini.

Route::get('/{any}', function(){
    return view('welcome');
})->where('any', '.*');

Kemudian ubah html welcome.blade.php dengan di bawah ini.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="csrf-token" content="{{csrf_token()}}">
    <title>Laravel</title>
    <link href=" {{ mix('css/app.css') }}" rel="stylesheet">
  </head>
  <body>
    <div id="app">
      <app></app>
    </div>
    <script src="{{ mix('js/app.js') }}"></script>
  </body>
</html>

Silahkan lihat Cara Install Vue.js di Laravel untuk penjelasan lainnya mengenai penginstalan vue.

Diatas kita telah mengkonfigurasi vue, sekarang kita mensetting bootstrap.

Buat folder baru di direktori resources dengan nama sass dan tambahkan file baru dengan nama app.scss, lalu import modul bootstrap.

//sass/app.scss
@import '~bootstrap/scss/bootstrap'; 

Kemudian buka resources/js/bootstrap.js dan tambahkan dibawah ini.

try {
  window.Popper = require('popper.js').default;
  window.$ = window.jQuery = require('jquery');

  require('bootstrap');
} catch (e) {}

Selanjutnya buka file webpack.mix.js lalu buat seperti dibawah ini.

mix.js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css')
    .sourceMaps();

Terakhir kita lakukan compiling.

	
npm run dev

Sampai disini instalasi vue dan bootstrap telah selesai dan kita sudah bisa menggunakannya.

Silahkan lihat Cara Install bootstrap di Laravel untuk penjelasan lainnya mengenai penginstalan bootstrap.

Menampilkan Data

Kita lanjutkan untuk menampilkan data yang ada di database dengan melakukan list rendering request ke endpoint api dengan axios.

Buka App.vue dan kita buat data properti dan method seperti dibawah. Kita akan gunakan App.vue sebagai induk / parent.

<script>    
  export default { 
    data(){
      return {
        categories : []  
      }
    },
    mounted(){
      this.getCategories()
    },
    methods: { 
      getCategories(){
        axios.get('api/category/allCategories')
        .then(response => { 
          this.categories = response.data;
          console.log(response.data)
        })
        .catch(error => {
          console.error(error);
        });
      }  
    }
  }
</script>
<template>
  <div class="container-sm m-4">
    <div class="all-categories mt-4">
      <table class="table table-bordered">
        <thead>
          <tr >
            <th scope="col">Kategori</th>
            <th scope="col"></th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="category in categories" :key="category.id">
            <td width="200">
              |---> <b>{{category.name}}</b> 
              <span v-for="childCat in category.children" :key="childCat.id">
                <p class="pl-4 m-0">  |---> {{childCat.name}}</p>
              </span>
            </td>
            <td width="200">
              <button class="btn btn-sm btn-primary" type="button" data-toggle="collapse" data-target="#addSub" aria-expanded="false" aria-controls="collapseExample">
              Tambah Sub Kategori
              </button>  
              <div class="collapse" id="addSub">
                <div class="card card-body m-3">
                  ...
                </div>
              </div>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</template>

Jangan lupa jalakan php artisan serve dan npn run dev; atau gunakan npm run watch untuk meng'compile otomatis setiap menyimpan perubahan.

Hasilnya seperti gambar berikut.

Cara Membuat Kategori dan Sub Kategori di Laravel + Vue.js

Form Input Kategori Baru

Setelah selesai menampilkan data kategori, selanjutnya mengerjakan form input untuk membuat kategori baru.

Kita buat komponen baru pada folder components dengan nama ParentForm.vue dan buat seperti dibawah ini.

<template> 
  <div class="parent-form mb-4"> 
    <form @submit.prevent="submit">
      <div class="form-group">
        <label for="name">Nama</label>
        <input type="text" class="form-control" v-model="category.name" placeholder="Nama kategori..">
      </div> 
      <button type="submit" class="btn btn-primary">Submit</button>
    </form>
  </div> 
</template>

<script>
  export default {
    name: 'parent-form',
     data(){
      return {
        category: {
          name: '', 
          parent_id: null
        }
      }
    },
     methods: {
      submit() {
       this.$emit('add-parent', this.category)
         this.category = {
          name: ''
        }
      }
    }
  }
</script>

Kita membuat costum event untuk mengirim atau meneruskan data value ke parent. Sekali lagi untuk parent_id disini kita buat value null untuk dijadikan sebagai indukan dari kategori.

Selanjutnya kita import pada App.vue dan kita buat event listener seperti dibawha ini.

<div class="container-sm m-4">

<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
Buat Kategori Baru
</button>

<div class="collapse" id="collapseExample">
  <div class="card card-body m-3">
    <parent-form @add-parent="addParent"></parent-form>
  </div>
</div>

<div class="all-categories mt-4">
...

Kita buat collapse agar lebih rapi.

Langkah selanjutnya kita buat method baru di dalam properti methods dengan nama addParent() seperti dibawah ini.

...
addParent(category){
 axios.post('api/category/create', category)
  .then(response => { 
     this.getCategories();
     console.log(response.data)
  })
   .catch(error => {
      console.error(error);
  });
},
...

Agar reaktif memperbaharui DOM setelah membuat data baru, kita tambahkan method getCategories() pada .then response.

Hasilnya seperti gambar dibawah ini. Silahkan mencoba membuat kategori baru.

Cara Membuat Kategori dan Sub Kategori di Laravel + Vue.js

Form Input Sub Kategori Baru

Bagian terakhir yang akan kita buat adalah form input untuk membuat sub kategori.

Kita buat kembali sebuah komponen dengan nama ChildForm.vue dengan form dan data properti yang sama dengan ParentForm.vue.

Hanya saja yang membedakan adalah kita perlu menambahkan value ke properti parent_id dengan props dan merubah nama event.

//ChildForm.vue
<template> 
  <div class="parent-form mb-4"> 
    <form @submit.prevent="submit">
      <div class="form-group">
        <label for="name">Nama</label>
        <input type="text" class="form-control" v-model="category.name" placeholder="Nama sub kategori..">
      </div> 
      <button type="submit" class="btn btn-primary">Submit</button>
    </form>
  </div> 
</template>

<script>
  export default {
    name: 'parent-form',
    props: ['parentId'], 
     data(){
      return {
        category: {
          name: '', 
          parent_id: this.parentId
        }
      }
    },
     methods: {
      submit() {
       this.$emit('add-child', this.category)
         this.category = {
          name: ''
        }
      }
    }
  }
</script> 

Lalu kita import ke App.vue dan letakan di dalam element form td seperti dibawah.

...
<td width="200">
  <button class="btn btn-sm btn-primary" @click="addParentId(category.id)" type="button" data-toggle="collapse" :data-target="'#addSub' + category.id" aria-expanded="false" aria-controls="collapseExample">
  Tambah Sub Kategori
  </button>  
  <div v-if="parentId === category.id">
    <div class="collapse" :id="'addSub' + category.id">
      <div class="card card-body m-3">
        <child-form @add-child="addChild" :parentId="parentId"></child-form>
      </div>
    </div>
  </div>
</td>
...
<script>   
  import ChildForm from './ChildForm'
  ... 
  
  export default {
    components: {
      ChildForm,
      ...
    },
    data(){
      return {
        categories : [], 
        parentId: '',  
      }
    },
    mounted(){
      this.getCategories()
    },
    methods: { 
      addParentId(id){
        this.parentId = id;
      },
      
      ...
      
      addChild(category){
        axios.post('api/category/create', category)
        .then(response => { 
          this.getCategories();
          this.parentId = '';
          console.log(response.data)
        })
        .catch(error => {
          console.error(error);
        });
      }
    }
  }
</script>

Mari lihat button diatas. Kita membuat click event beserta method addParentId() dan dengan argument.

Ketika button di klik, kita teruskan data berupa id kategori ke properti parent_id yang dikirim ke komponen ChildForm dengan props sebagai data value untuk properti parent_id.

Juga kita buat kondisi perbandingan untuk membuka form dengan melihat kesesuaian form input yang akan terbuka ketika di klik.

Silahkan dicoba membuat sub kategori baru.

Cara Membuat Kategori dan Sub Kategori di Laravel + Vue.js

Sampai disini proses pembuatan kategori dan sub kategori telah selesai.

Kita telah membuat proses insert atau membuat data dan menampilkannya. Jika kurang jelas atau terjadi error silahkan ditanyakan.

Silahkan dikerjakan dan dikembangkan.

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel

Berlangganan

Berlangganan untuk mendapat pemberitahuan artikel terbaru via email.