Laravel 8 Vue Js CRUD Example Tutorial Single Page Application

Throught Laravel 8 Vue Js CRUD example tutorial; we learn laravel 8 vue js crud example step by step easy way. More then beginners want to build crud operation with laravel vue in simple application so we domestrate the best way to Create, Read, Update and Delete (CRUD) using laravel 8 and vue js. A crud operation web application where you can Create, Retrieve, Update, Delete Posts. Backend in Laravel PHP framework and Frontend in Vue JS framework.

Laravel is one of the demanding web development frameworks nowadays and the vue is most usefuly and easy working js framework to use laravel. Throughout this articale, we’ll be learning how to create a CRUD app with Laravel 8 and vuejs to create, insert, update and delete products from a MySQL database.

Laravel 8 Vue JS CRUD (SPA) Example Steps

Let’s start creating Laravel Vue Js CRUD operation step by step full with easy and best coding part available.

  1. Install Laravel 8 App
  2. Setup Database
  3. Create Migration, Model
  4. Create Controller
  5. Update Code in Web.php for Api routes
  6. Add Routes in api.php
  7. Install Laravel Vue UI
  8. Initiate Vue in Laravel
  9. Create Vue CRUD Components
  10. Create Vue Routes for Laravel Vue CRUD
  11. Include Dependencies to app.js
  12. Run Development Server

Step 1: Install Laravel Project

First open your terminal and run nthe following command for creating new laravel project.

composer create-project laravel/laravel laravel-vue-crud --prefer-dist

Step 2: Setup Database

Now, you need to visit the downloaded laravel 8 app root directory and open .env file. Then add database details as follow:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=<DATABASE NAME>
DB_USERNAME=<DATABASE USERNAME>
DB_PASSWORD=<DATABASE PASSWORD>

Step 3: Generate Model and Run Migration

Run the below command for generating model file along with migration. This command added Product model and 2021_07_15_025120_create_products_table table.

php artisan make:model Product -m

Add Following code in database\migrations\2021_07_15_025120_create_products_table.php

<?php

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

class CreateProductsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('name')->nullable();
            $table->string('description')->nullable();
            $table->decimal('price')->nullable()->default(0.00);
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('products');
    }
}

Add fillable properties in your app/Models/Product.php model.

app\Models\Product.php

<?php

namespace App\Models;

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

class Product extends Model
{
    use HasFactory;

    protected $fillable = [
      'name', 'description', 'price'
    ];
}

Next, you need to evoke migration with below command:

php artisan migrate

Step 4: Create Controller

Noe create controller for crud operation. Here we are using Product Controller you can use as per your requirements.

php artisan make:controller Api/ProductController

Open and update the below code in app\Http\Controllers\ProductController.php

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Product;

class ProductController extends Controller
{
    public function index()
    {
        $products = Product::orderby('id', 'desc')->get();

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

    public function store(Request $request)
    {

        $product = Product::create($request->all());

        return response()->json([
            'status' => 'success',
            'product'   => $product
        ]);
    }

    public function show($id)
    {
        $product = Product::find($id);

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

    public function update(Request $request, $id)
    {
        $product = Product::find($id);
        $product->update($request->all());

        return response()->json([
            'status' => 'success',
            'post'   => $product
        ]);
    }

    public function destroy($id)
     {
         $product = Product::find($id);
         $product->delete();

         return response()->json('Product successfully deleted!');
     }
}

Step 5: Create Routes

Open routes/web.php file and add below routes on it. The below code is work for api routes when we use use api routes we need to update something just like below code.

routes/web.php

<?php

use Illuminate\Support\Facades\Route;

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

Now we use api routes for laravel vue crud, so open your routes/api.php file and update the routes something like below.

routes/api.php

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Api\ProductController;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::middleware('api')->group(function () {
    Route::resource('products', ProductController::class);
});

Route::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});

Step 6: Install Laravel Vue UI

Now we use the vue js dependencies with laravel crud.

First run composer command to install Vue UI in laravel, it will manifest vue laravel scaffold.

composer require laravel/ui

Next run following command

php artisan ui vue

Now we need to install npm package with the follow commadn.

npm install

After that, use the command to install the vue router and vue axios packages. These packages are used to consume Laravel CRUD APIs.

npm install vue-router vue-axios

The npm run watch command compiles the assets, not just that with run watch command you don’t fret about re-run the compiler over and over again.

npm run watch

Step 7: Initiate Vue in Laravel

Now we will initiate the vue component with laravel see how we can.

We start from laravel, first we need to create a layouts folder inside the resources/views directory and then create an app.blade.php within it.

Place below code in resources/views/layouts/app.blade.php file.

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="csrf-token" value="{{ csrf_token() }}" />

    <title>Vue JS CRUD Operations in Laravel</title>

    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>

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

</html>

Step 8: Create Vue CRUD Components

Next we add app.vue inside resources js directory which will show menues and we initiate the router view here.

So, create app.vue file in resources/js folder, put the below code in resources/js/app.vue file:

resources\js\app.vue

<template>
    <div class="container">
        <nav class="navbar navbar-expand-lg navbar-light bg-light">
            <div class="collapse navbar-collapse">
                <div class="navbar-nav">
                    <router-link :to="{ name: 'ProductIndex' }"  class="nav-item nav-link">Products</router-link>
                </div>
            </div>
        </nav>
        <router-view> </router-view>
    </div>
</template>

<script>
    export default {}
</script>

Now we create products folder ‘procuts’ inside resources/js/components directory, then we need to add our template here just like below. we create three component one index.vue which will list the produts, another is create.vue which will show the product create form and another is edit.vue which will use for edit the product.

  • index.vue
  • create.vue
  • edit.vue

First open resources/js/components/products/index.vue file and put below code on it.

<template>
    <div class="container">
        <h2 class="text-center">Products List</h2>
        <div class="row">
            <div class="col-md-12">
                <router-link :to="{ name: 'ProductCreate' }" class="btn btn-primary btn-sm float-right mb-2">Add Product</router-link>
            </div>
        </div>
        <div class="row">
            <div class="col-md-12">
                <table class="table">
                    <thead>
                    <tr>
                        <th>#</th>
                        <th>Name</th>
                        <th>Description</th>
                        <th>Price</th>
                        <th>Actions</th>
                    </tr>
                    </thead>
                    <tbody>
                        <tr v-for="(product, key) of products">
                            <td>{{ key+1 }}</td>
                            <td>{{ product.name }}</td>
                            <td>{{ product.description }}</td>
                            <td>{{ product.price }}</td>
                            <td>
                                <router-link class="btn btn-success btn-sm" :to="{ name: 'ProductEdit', params: { productId: product.id }}">Edit</router-link>
                                <button class="btn btn-danger btn-sm" @click="deleteProduct(product.id)">Delete</button>
                            </td>
                            <td>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                products: {}
            }
        },
        created() {
            this.getProducts();
        },
        methods: {
            getProducts() {
              this.axios.get('http://127.0.0.1:8000/api/products').then(response => {
                this.products = response.data;
            }).catch(error=>{
                console.log(error)
            })
            },
            deleteProduct(productId) {
                this.axios
                    .delete(`http://127.0.0.1:8000/api/products/${productId}`)
                    .then(response => {
                        let i = this.products.map(data => data.id).indexOf(productId);
                        this.products.splice(i, 1)
                    });
            }
        }
    }
</script>

Place code in resources/js/components/products/create.vue file:

<template>
    <div class="container">
        <h2 class="text-center">Create product</h2>
        <div class="row">
            <div class="col-md-12">
                <router-link :to="{ name: 'ProductIndex' }" class="btn btn-primary btn-sm float-right mb-2">Back</router-link>
            </div>
        </div>
        <div class="row">
            <div class="col-md-12">
                <form>
                    <div class="form-group">
                        <label>Name</label>
                        <input type="text" class="form-control" v-model="product.name">
                    </div>
                    <div class="form-group">
                        <label>Description</label>
                        <textarea type="text" rows="5" class="form-control" v-model="product.description"></textarea>
                    </div>
                    <div class="form-group">
                        <label>Price</label>
                        <input type="number" class="form-control" v-model="product.price">
                    </div>
                    <button type="button" class="btn btn-primary" @click="createProduct()">Create</button>
                </form>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                product: {}
            }
        },
        methods: {
            createProduct() {
                this.axios.post('http://127.0.0.1:8000/api/products', this.product)
                    .then(response => {
                        this.$router.push({ name: 'ProductIndex' })
                    })
                    .catch(error=>{
                      console.log(error)
                    })
            }
        }
    }
</script>

One more open resources/js/components/products/edit.vue template and add the below code:

<template>
    <div class="container">
        <h2 class="text-center">Update Product</h2>
        <div class="row">
            <div class="col-md-12">
                <router-link :to="{ name: 'ProductIndex' }" class="btn btn-primary btn-sm float-right mb-2">Back</router-link>
            </div>
        </div>
        <div class="row">
            <div class="col-md-12">
                <form>
                    <div class="form-group">
                        <label>Name</label>
                        <input type="text" class="form-control" v-model="product.name">
                    </div>
                    <div class="form-group">
                        <label>Description</label>
                        <textarea type="text" rows="5" class="form-control" v-model="product.description"></textarea>
                    </div>
                    <div class="form-group">
                        <label>Price</label>
                        <input type="text" class="form-control" v-model="product.price">
                    </div>
                    <button type="button" class="btn btn-primary" @click="updateProduct()"> Update </button>
                </form>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                product: {}
            }
        },
        mounted() {
            this.editProduct(this.$route.params.productId);
        },
        methods: {
            editProduct(productId) {
                this.axios.get(`http://127.0.0.1:8000/api/products/${productId}`)
                   .then((response) => {
                       this.product = response.data;
                   });
            },
            updateProduct() {
                this.axios
                    .patch(`http://127.0.0.1:8000/api/products/${this.$route.params.productId}`, this.product)
                    .then((response) => {
                        this.$router.push({ name: 'ProductIndex' });
                    });
            }
        }
    }
</script>

Step 9: Create Vue Routes for Laravel Vue CRUD

Now we create new file routes.js inside resources/js directory, and we will add the code in the resources/js/routes.js file:

import ProductIndex from './components/products/index.vue';
import ProductCreate from './components/products/create.vue';
import ProductEdit from './components/products/edit.vue';

export const routes = [
    {
        path: '/products',
        component: ProductIndex,
        name: "ProductIndex"
    },
    {
        path: '/products/create',
        component: ProductCreate,
        name: "ProductCreate"
    },
    {
        path: '/products/edit/:productId',
        component: ProductEdit,
        name: "ProductEdit"
    }
];

Step 10: Include Dependencies to app.js

Now in this step we include the required packages in the app.js file. So open resources/js/app.js and update the below code on it.

resources\js\app.js

/**
 * First we will load all of this project's JavaScript dependencies which
 * includes Vue and other libraries. It is a great starting point when
 * building robust, powerful web applications using Vue and Laravel.
 */

require('./bootstrap');
import Vue from 'vue'; // if this is not work add this =>  window.Vue = require('vue');

import axios from 'axios';
import VueAxios from 'vue-axios';
import VueRouter from 'vue-router';

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

import App from './app.vue';
import { routes } from './routes';


const router = new VueRouter({
    mode: 'history',
    routes: routes
});

const app = new Vue({
    el: '#app',
    router: router,
    render: h => h(App),
});

Step 11: Run Development Server

After the all requiremets of laravel 8 vue js crud now we run the npm run watch file which is initialise our vue files and show success. After that we run the serve or you can use your virtual host domain url here.

npm run watch
php artisan serve

If not use below code

http://127.0.0.1:8000/

If you getting Error: Cannot find module ‘webpack/lib/rules/DescriptionDataMatcherRulePlugin’ Require stack error message then you need to update your vue-loader

npm update vue-loader

Now Laravel Vue js Crud operation hopefully completed with this beautiful article. If you have any question or query please let me know in comment box. Feel free for more upate follow us on social networks.

1 thought on “Laravel 8 Vue Js CRUD Example Tutorial Single Page Application”

Leave a Comment