Ilmu Coding Ilmucoding.com - Merupakan situs yang membantu Anda belajar coding lebih mudah, nyaman, interaktif dan profesional. Belajar sekarang di ilmu coding. GRATIS

Tutorial CRUD Menggunakan Laravel 7 dan Vue Js

10 min read

Tutorial CRUD Laravel 7 dan Vue Js

Halo artisan, jika Anda membutuhkan tutorial membuat CRUD menggunakan laravel 7 dan vue Js, ini merupakan bacaan yang tepat.

… dengan membaca artikel ini, Anda akan mempelajari:

  1. Cara menginstall Vue Js di Laravel
  2. Implementasi sistem CRUD sederhana menggunakan Laravel 7 dan Vue Js
  3. Belajar SweatAlert di Vue Js
  4. dan masih banyak lagi…

Tutorial ini saya khususnya untuk pemula yang ingin mengimplementasikan React Js di Laravel. Namun tidak menutup kemungkinan Anda yang sudah terbiasa pun dapat mengikuti tutorial ini.

Yuk langsung aja kita mulai…

Pendahuluan

Apa itu Vue Js? Vue js merupakan framework JavaScript yang bersifat progresif dan open source untuk membangun antarmuka / UI suatu website yang dibuat oleh Evan You. Framework ini pertama kali rilis pada bulan Februari 2014 dan rilis versi stabil pada bulan Desember 2019.

Vue Js didukung oleh pustaka Javascript yang lengkap dan sangat mudah dimplementasikan. Meski bagitu, Vue Js masih dapat digabungkan dengan bahasa HTML dan CSS yang tidak banyak perubahan. Sehingga, Anda tidak akan kesulitan mempelajarinya.

Rekomendasi: Cara Install dan Menggunakan Vue Js di Laravel 7

Nah, jika Anda baru pertama kali menggunakan Vue Js di Laravel, ada baiknya membaca artikel yang saya rekomendasikan di atas terlebih dahulu.

Jika sudah, kita akan menuju tutorial CRUD menggunakan Laravel 7 dan Vue Js.

Siap?

Tools yang Diperlukan

Sebelum masuk ke pembahasan, kita persiapkan dulu toolsnya, yaitu:

  1. Web Server (XAMPP, WAMP, Nginx, Laragon, dll) – Saya menggunakan Laragon.
  2. Composer
  3. Node Js – Saya menggunakan Node Js versi 12.16.2
  4. Text Editor (Sublime Text, Atom, Notepad, dll) – Saya menggunakan Visual Studio Code

Udah itu aja?

Iya, itu saja.

Cek Kelengkapan Installasi

1# AKtifkan web server yang Anda gunakan. Pilih aktif untuk apache dan mysql.

2# Cek kelengkapan Node Js dengan mengetik perintah node -v dan npm -v. Biasanya npm akan otomatis terinstall saat menginstall Node Js.

3# Cek aktifasi composer dengan menggunakan perintah composer di command promp atau terminal Anda.

Silahkan buka terminal atau command prompt Anda dan cobalah ketik perintah yang saya sebutkan di atas.

Perhatikan gambar di bawah ini:

Jika sudah muncul seperti gambar di atas, artinya paket installasi sudah lengkap.

Akhirnya, kita sudah bisa menggunakannya untuk menginstall Laravel dan Vue Js.

Yuk lanjut.

Membuat Project Laravel

Mari kita siapkan untuk membuat project Laravel. Pertama-tama, Anda perlu menetapkan di mana ingin menginstall Laravel.

Rekomendasi: Tutorial Cara Install Laravel 7 dengan Composer

Kalau saya, akan menginstall di direktori D:/laragon/www/laravel.

Anda di mana?

Jika sudah memutuskan, silahkan masuk ke dalam direktorinya, dan install Laravel dengan perintah:

composer create-project  --prefer-dist laravel/laravel blog_vue

Perhatikan gambar di bawah ini:

Silahkan tunggu sampai proses installasi selesai.

Install Package Laravel UI

Pada versi terbaru, Laravel telah memisahkan pengguna dengan UI nya.

Bukan berarti Laravel menghilangkan bagian UI. Hanya saja, kita perlu menginstallnya secara terpisah menggunakan perintah composer require laravel/ui.

Perhatikan gambar berikut:

Install Vue Js di Laravel

Sekarang, kita akan menginstall Vue Js di project blog_vue menggunakan perintah php artisan ui vue.

Perhatikan gambar di bawah ini:

Install Node Js di Laravel

Sekarang Anda bisa menginstall Node Js di Laravel dengan menggunakan perintah npm install. Seperti yang kita bahas di awal, jika sudah menginstall Node Js, biasanya sudah include npm. Oleh sebab itu kita bisa menggunakan perintah npm install.

Rekomendasi: Belajar Node Js untuk Pemula

Perhatikan gambar di bawah ini:

Membuat Project CRUD Laravel 7 dengan Vue Js

Kita masuk ke pembahasan utama bagaimana membuat fitur CRUD pada Laravel 7 dan Vue Js. Berikut tata caranya:

Membuat Database, Table dan Konfigurasinya

Step 1 – Buat database baru bernama db_blog_vue.

Step 2 – Buka file .env dan cari kode berikut:

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

Ubah menjadi:

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

Step 3 – Membuat table articles di database db_blog_vue

Ketik perintah php artisan make:model Article --migration untuk menambahkan migration baru dan model baru.

Perhatikan gambar berikut ini:

Tutorial CRUD Laravel 7 dan Vue Js Bagian 7

Step 4 – Buka file _create_article_table.php dan masukan kode di bawah ini:

Schema::create('articles', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->string('title');
    $table->string('content');
    $table->timestamps();
});

Perhatikan gambar di bawah ini:

Tutorial CRUD Laravel 7 dan Vue Js Bagian 3

Step 5 – Buka file Article.php dan tambahkan kode berikut:

protected $table = "articles";
protected $fillable = ['title', 'content']; 

Perhatikan gambar berikut:

Tutorial CRUD Laravel 7 dan Vue Js

Step 6 – Ketik perintah php artisan migrate agar table yang kita buat bisa terbentuk di database db_blog_vue.

Perhatikan gamabr berikut:

Hasilnya:

Membuat Halaman View App

Silahkan buat file baru bernama app.blade.php dan kemudian ketik kode program di bawah ini:

<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

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

    <title>Vue Laravel</title>

    <!-- Styles -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
    <div id="app"></div>

    <script src="{{ asset('js/app.js') }}"></script>
</body>
</html>

Lalu simpan.

Perhatikan gambar berikut:

Tutorial CRUD Laravel 7 dan Vue Js Bagian 4

Memodifikasi Route Web dan Api

Step 1 – Tambahkan Route berikut ini di dalam file routes/web.php:

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

Perhatikan gambar berikut:

Tutorial CRUD Laravel 7 dan Vue Js Bagian 6

Step 2 – Tambahkan Route API

Silahkan buka file routes/api.php dan tambahkan kode berikut ini:

Route::get('/articles', 'ArticleController@index');
Route::post('/article/store', 'ArticleController@store');
Route::get('/article/edit/{id}', 'ArticleController@getArticle');
Route::get('/article/show/{id}', 'ArticleController@getArticle');
Route::put('/article/update/{id}', 'ArticleController@update');
Route::delete('/article/delete/{id}', 'ArticleController@delete'); 

Install Vue Axios, Vue Router dan Vue Sweet Alert2 di Laravel

Kita akan menggunakan vue router untuk menghandle perpindahan antar halaman, vue axios kita gunakan untuk menghandle pertukaran data antar front end – backend dan sweat alert akan digunakan sebagai notifikasi jika berhasil melakukan delete, create dan update.

Anda bisa menggunakan perintah npm install vue-axios vue-router vue-sweetalert2 --save untuk menginstall keduanya. npm i vue-sweetalert2

Perhatikan gambar di bawah ini:

Membuat File Pendukung CRUD Laravel 7 dan Vue Js

Step 1 – Buat controller bernama ArticleController.php dengan mengetik perintah php artisan make:controller ArticleController.

Step 2 – Lengkapi kode pada file ArticleController.php dengan kode berikut:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ArticleController extends Controller
{
    public function index()
    {
        $articles = \App\Article::all();

        return $articles->toJson();
    }

    public function store(Request $request)
    {
        $validatedData = $request->validate([
          'title' => 'required',
          'content' => 'required',
        ]);

        $project = \App\Article::create([
          'title' => $validatedData['title'],
          'content' => $validatedData['content'],
        ]);

        $msg = [
            'success' => true,
            'message' => 'Article created successfully!'
        ];

        return response()->json($msg);
    }

    public function getArticle($id) // for edit and show
    {
        $article = \App\Article::find($id);

        return $article->toJson();
    }

    public function update(Request $request, $id)
    {
        $validatedData = $request->validate([
          'title' => 'required',
          'content' => 'required',
        ]);

        $article = \App\Article::find($id);
        $article->title = $validatedData['title'];
        $article->content = $validatedData['content'];
        $article->save();

        $msg = [
            'success' => true,
            'message' => 'Article updated successfully'
        ];

        return response()->json($msg);
    }

    public function delete($id)
    {
        $article = \App\Article::find($id);
        if(!empty($article)){
            $article->delete();
            $msg = [
                'success' => true,
                'message' => 'Article deleted successfully!'
            ];
            return response()->json($msg);
        } else {
            $msg = [
                'success' => false,
                'message' => 'Article deleted failed!'
            ];
            return response()->json($msg);
        }
    }
}

Step 3 – Buat file CRUD dengan Vue Js

Saya akan memberikan gambaran untuk menyusun folder dan letak file yang akan kita buat. Perhatikan gambar di bawah ini:

Penjelasan:

  1. File app.js akan kita gunakan sebagai route dan mengimport package yang dibutuhkan.
  2. File App.vue kita gunakan sebagai template dan router view-nya.
  3. File ArticleCreate.vue akan kita gunakan untuk menampilkan halaman tambah artikel.
  4. Pada file ArticleEdit.vue akan kita gunakan untuk menampilkan halaman edit artikel.
  5. Pada file ArticleIndex.vue akan kita gunakan untuk menampilkan semua halaman index artikel.
  6. Sedangkan ArticleShow.vue akan kita gunakan untuk menampilkan detail artikel.

Silahkan buat structure folder seperti itu ya.

app.js

require('./bootstrap');

window.Vue = require('vue');

import VueRouter from 'vue-router';
import VueAxios from 'vue-axios';
import axios from 'axios';
import App from './components/App.vue';
import VueSweetalert2 from 'vue-sweetalert2'; 
// If you don't need the styles, do not connect
import 'sweetalert2/dist/sweetalert2.min.css';

Vue.use(VueRouter);
Vue.use(VueSweetalert2);
Vue.use(VueAxios, axios);

import ArticleIndex from './components/ArticleIndex.vue';
import ArticleCreate from './components/ArticleCreate.vue';
import ArticleShow from './components/ArticleShow.vue';
import ArticleEdit from './components/ArticleEdit.vue';

const routes = [
  {
      name: 'home',
      path: '/',
      component: ArticleIndex
  },
  {
      name: 'create',
      path: '/article/create',
      component: ArticleCreate
  },
  {
      name: 'edit',
      path: '/article/edit/:id',
      component: ArticleEdit
  },
  {
    name: 'show',
    path: '/article/show/:id',
    component: ArticleShow
}
];

const router = new VueRouter({ mode: 'history', routes: routes});
const app = new Vue(Vue.util.extend({ router }, App)).$mount('#app');

App.vue:

<template>
    <div class="page">
        <nav class='navbar navbar-dark bg-dark'>
            <div class='container'>
                <router-link :to="{ name: 'home' }" class="navbar-brand">Ilmu Coding</router-link>
            </div>
        </nav>
        <router-view></router-view>
    </div>
</template>

ArticleCreate.vue:

<template>
    <div class='container py-4'>
        <div class='row justify-content-center'>
            <div class='col-md-6'>
                <div class='card'>
                    <div class='card-header'>Create Article</div>
                    <div class='card-body'>
                        <div class="alert alert-danger" v-if="errors.length">
                            <b>Terdapat kesalahan dalam input data:</b>
                            <ul>
                                <li v-for="error in errors" :key="error">{{ error }}</li>
                            </ul>
                        </div>

                        <form @submit.prevent="createArticle">
                            <div class='form-group'>
                                <label htmlFor='title'>Title</label>
                                <input type="text" class="form-control" id="title" v-model="article.title">
                            </div>
                            <div class='form-group'>
                                <label htmlFor='content'>Content</label>
                                <textarea type="text" class="form-control" id="content" v-model="article.content" rows="5"></textarea>
                            </div>
                            <div class='form-group'>
                                <router-link :to="{ name: 'home' }" class="btn btn-secondary">Back</router-link>
                                &nbsp;
                                &nbsp;
                                <button class='btn btn-primary'>Create</button>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
    export default {
        data(){
            return {
                article:{},
                errors: [],
                title: null,
                content: null,
            }
        },
        methods: {
            createArticle(e){
                
                if (this.$data.article.title != null && this.$data.article.content != null) {
                    this.$swal.fire({
                        title: 'Success',
                        text: "Article created successfully",
                        icon: 'success',
                        timer: 1000
                    })
                    let uri = '/api/article/store';
                    this.axios.post(uri, this.article).then((response) => {
                        this.$router.push({name: 'home'});
                    });
                    return true;
                }

                this.errors = [];

                if (!this.title) {
                    this.errors.push('Title wajib diisi !');
                }
                if (!this.content) {
                    this.errors.push('Content wajib diisi !');
                }

                e.preventDefault();
            }
        }
    }
</script>

ArticleEdit.vue:

<template>
    <div class='container py-4'>
        <div class='row justify-content-center'>
            <div class='col-md-6'>
                <div class='card'>
                    <div class='card-header'>Edit Article</div>
                    <div class='card-body'>
                        <div class="alert alert-danger" v-if="errors.length">
                            <b>Terdapat kesalahan dalam input data:</b>
                            <ul>
                                <li v-for="error in errors" :key="error">{{ error }}</li>
                            </ul>
                        </div>

                        <form @submit.prevent="updateArticle">
                            <div class='form-group'>
                                <label htmlFor='title'>Title</label>
                                <input type="text" class="form-control" id="title" v-model="article.title">
                            </div>
                            <div class='form-group'>
                                <label htmlFor='content'>Content</label>
                                <textarea type="text" class="form-control" id="content" v-model="article.content" rows="5"></textarea>
                            </div>
                            <div class='form-group'>
                                <router-link :to="{ name: 'home' }" class="btn btn-secondary">Back</router-link>
                                &nbsp;
                                &nbsp;
                                <button class='btn btn-primary'>Create</button>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
    export default {
        data(){
        return {
            article:{},
            errors: [],
            title: null,
            content: null,
        }
    },
    created() {
        let uri = `/api/article/edit/${this.$route.params.id}`;
        this.axios.get(uri).then((response) => {
            this.article = response.data;
        });
    },
    methods: {
        updateArticle(e){
            
            if (this.$data.article.title != null && this.$data.article.content != null) {
                
                this.$swal.fire({
                    title: 'Success',
                    text: "Article created successfully",
                    icon: 'success',
                    timer: 1000
                });
                let uri = `/api/article/update/${this.$route.params.id}`;
                this.axios.put(uri, this.article).then((response) => {
                    this.$router.push({name: 'home'});
                });
                return true;
            }


            this.errors = [];

            if (!this.title) {
                this.errors.push('Title wajib diisi !');
            }
            if (!this.content) {
                this.errors.push('Content wajib diisi !');
            }

            e.preventDefault();
        }
    }
  }
</script>

ArticleIndex.vue:

<template>
    <div class='container py-4'>
        <div class='row justify-content-center'>
            <div class='col-md-8'>
            <div class='card'>
                <div class='card-header'>All Article</div>
                <div class='card-body'>
                    <router-link :to="{ name: 'create' }" class="btn btn-primary">Create new article</router-link>
                    <br/>
                    <br/>
                    <div class="table-responsive">
                        <table class="table table-bordered table-hover">
                            <thead>
                                <tr>
                                    <th width="50" class="text-center">No</th>
                                    <th>Title</th>
                                    <th width="200" class="text-center">Action</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr v-for="(article, index) in articles" :key="article.id">
                                    <td width="50" class="text-center">{{ index + 1 }}</td>
                                    <td>{{ article.title }}</td>
                                    <td width="200" class="text-center">
                                        <div class="btn-group">
                                            <router-link :to="{name: 'show', params: { id: article.id }}" class="btn btn-primary">Detail</router-link>
                                            <router-link :to="{name: 'edit', params: { id: article.id }}" class="btn btn-success">Edit</router-link>
                                            <button class="btn btn-danger" @click = "deletePost(article.id)">Delete</button>
                                        </div>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
            </div>
        </div>
        </div>
</template>

<script>
  export default {
      data() {
        return {
          articles: []
        }
      },
      created() {
        let uri = 'api/articles';
        this.axios.get(uri).then(response => {
            this.articles = response.data;
        });
    },
    methods: {
        deletePost(id)
        {
            this.$swal.fire({
                title: 'Apakah kamu yakin?',
                text: "Jika kamu hapus, maka data tidak akan kembali lagi.",
                icon: 'warning',
                showCancelButton: true,
                confirmButtonColor: '#3085d6',
                cancelButtonColor: '#d33',
                confirmButtonText: 'Hapus Deh',
                cancelButtonText: 'Nggak Jadi'
                }).then((result) => {
                if (result.value) {
                    this.$swal.fire({
                        title: 'Success!',
                        text: 'Article deleted successfully',
                        icon: 'success',
                        timer: 1000
                    });
                    let uri = `api/article/delete/${id}`;
                    this.axios.delete(uri).then(response => {
                        this.articles.splice(this.articles.indexOf(id), 1);
                    });
                    console.log("Deleted article with id ..." +id);
                }
            })
        }
    }
  }
</script>

ArticleShow.vue:

<template>
    <div class='container py-4'>
        <div class='row justify-content-center'>
            <div class='col-md-6'>
                <div class='card'>
                    <div class='card-header'>Detail Article</div>
                    <div class='card-body'>
                        <div class='form-group'>
                            <label htmlFor='title'>Title</label>
                            <input type="text" class="form-control" id="title" v-model="article.title" disabled>
                        </div>
                        <div class='form-group'>
                            <label htmlFor='content'>Content</label>
                            <textarea type="text" class="form-control" id="content" v-model="article.content" rows="5" disabled></textarea>
                        </div>
                        <div class='form-group'>
                            <router-link :to="{ name: 'home' }" class="btn btn-secondary">Back</router-link>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
    export default {
        data(){
        return {
            article:{},
        }
    },
    created() {
        let uri = `/api/article/show/${this.$route.params.id}`;
        this.axios.get(uri).then((response) => {
            this.article = response.data;
        });
    },
    method: {

    }
  }
</script>

Selesai.

Compiling dan Testing Laravel 7 dan Vue Js

Sekarang waktunya untuk memberikan perintah npm run dev agar kode yang sudah kita busat bisa diperbarui dan dijalankan.

Perhatikan gambar berikut ini:

Terakhir silahkan testing dengan melakukan perintah php artisan serve.

Perhatikan gambar di bawah ini:

Sekarang buka URL localhost:8000 dan hasilnya:

Silahkan lakukan create, detail, edit dan delete.

Enjoy!

Apa Selanjutnya?

Sekarang Anda sudah menyelesaikan serangkaian tutorial CRUD menggunakan Laravel 7 dan Vue Js.

Selamat.

… tapi jangan puas dulu.

Mungkin Anda mau mencoba tutorial berikut ini:

Tutorial CRUD Laravel 7 dan React Js

Oh iya, Anda bisa mendownload source code melalui link Github di bawah ini:

Source Code CRUD Laravel 7 dan Vue Js

… dan jika ada error program, silahkan beri komentar di bawah ya.

Selamat belajar …

Ilmu Coding Ilmucoding.com - Merupakan situs yang membantu Anda belajar coding lebih mudah, nyaman, interaktif dan profesional. Belajar sekarang di ilmu coding. GRATIS

4 Replies to “Tutorial CRUD Menggunakan Laravel 7 dan Vue Js”

  1. Terimakasih tutorialnya! saya terbantu sekali blajar Vue dari tutorial ini. yg di bagian Delete (hapus), itu salah. Seharusnya:

    this.articles.splice(this.articles.indexOf(id) – 1, 1);

  2. if ERROR in ./src/css/scss/site.scss
    Module build failed (from ./node_modules/css-loader/index.js):
    ModuleBuildError: Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
    Error: Dart Sass version 1.23.0-module.beta.1 is incompatible with ^1.3.0.

    I solved this incident by doing the following:
    npm uninstall –save-dev sass-loader
    npm install –save-dev sass-loader@7.1.0

Leave a Reply

Your email address will not be published. Required fields are marked *

Jika terbantu dengan artikel ini, silahkan share, beri komentar dan "klik" 1 kali pada iklan ya.