How to make a Laravel Single Page application with Vue JS?

How to make a Laravel Single Page application with Vue JS?

In this article, you will learn to make a Laravel Single Page Application with Vue JS. But You should have familiar with Laravel basic CRUD Operations. If you don’t please check this link: https://www.engineerjagat.com/how-to-create-an-application-in-laravel-8/

Let’s get started to Build a Laravel Single Page Application

Step 1: Install Laravel Application

 composer create-project laravel/laravel eproduct

Step 2: Database Configuration

After installing the Application find .env file, configure your database as shown below:

Step – 3: Migration

php artisan make:migration create_products_table --create=products

After Migrating we can add fields to our Table. So to do that we need to go “database/migrations “

<?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('title');
            $table->decimal('price');
            $table->string('description');
            $table->timestamps();
        });
    }

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

Now, Migrate your Database and check if the fields were created or not?

php artisan migrate

Step 4: Add Controller and Model

php artisan make:controller ProductController --resource --model=Product

After running this command we will see the model is created at “app/Models/Product.php”  and Controller is created as “app/Http/Controllers/ProductController.php “

Add Some Code in Product.php Model

 protected $fillable = [
        'title',
        'price',
        'description'
    ];

Add Code in “app/Http/Controllers/ProductController.php “

<?php

namespace App\Http\Controllers;

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

class ProductController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
         $products = Product::orderBy('created_at', 'desc')->take(10)->get();
         return $products;
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $product = new Product([
            'name' => $request->input('name'),
            'detail' => $request->input('detail')
        ]);
        $product->save();

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

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\Product  $product
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $product = Product::find($id);
        return response()->json($product);
    }

    /**
     * for editing the specified resource.
     *
     * @param  \App\Models\Product  $product
     * @return \Illuminate\Http\Response
     */
    public function edit(Product $product)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Product  $product
     * @return \Illuminate\Http\Response
     */
    public function update($id, Request $request)
    {
        $product = Product::find($id);
        $product->update($request->all());

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

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\Product  $product
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        $product = Product::find($id);
        $product->delete();

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

Step 5: Add Routes

We need to add routes for CRUD in routes/web.php

<?php

use Illuminate\Support\Facades\Route;

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

After Adding routes in routes/web.php now we need to add routes for CRUD API in routes/api.php 

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProductController;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
*/


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

Step 6: Install Laravel Vue UI

composer require laravel/ui
php artisan ui vue

Now install Vue Axios packages because they are used to consume Laravel CRUD APIs.

npm install vue-router vue-axios

We don’t need to run compiler agarin and again because of this command, so run this command:

npm run watch

Now, we need to create views or designs for our Application using Vue JS

Step 7: Setup Vue application in Laravel

To setup Vue JS in Laravel Application, we need to add views so create file app.blade.php in resources/views/app.blade.php

<!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>Product Management App </title>

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

<body>
    <div id="app"></div>
    <script src="{{ mix('js/app.js') }}" type="text/javascript"></script>
</body>

</html>

Step 8: Create Vue Components

Vue Components are the files that help us to CRUD the Application.

First, we have to create App.vue in resources/js/components/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="/" class="nav-item nav-link">Smartphone List</router-link>
                    <router-link to="/create" class="nav-item nav-link">Create Product</router-link>
                </div>
            </div>
        </nav>

        <router-view> </router-view>
    </div>
</template>
 
<script>
    export default {}
</script>

After this we need more functions like to show the product list, edit the product and remove or delete the product so I am going to create these files respectively.

  1. All.vue
  2. Create.vue
  3. Edit.vue

All.vue

<template>
    <div>
        <h2 class="text-center">Products List</h2>
 
        <table class="table">
            <thead>
            <tr>
                <th>Title</th>
                <th>Price</th>
                <th>Description</th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="product in products" :key="product.id">
                <td>{{ product.title }}</td>
                <td>{{ product.price }}</td>
                <td>{{ product.description }}</td>
                <td>
                    <div class="btn-group" role="group">
                        <router-link :to="{name: 'edit', params: { id: product.id }}" class="btn btn-sm btn-success">Edit</router-link>
                        <button class="btn btn-sm btn-danger" @click="deleteProduct(product.id)">Delete</button>
                    </div>
                </td>
            </tr>
            </tbody>
        </table>
    </div>
</template>
 
<script>
    export default {
        data() {
            return {
                products: []
            }
        },
        created() {
            this.axios
                .get('http://localhost:8000/api/products/')
                .then(response => {
                    this.products = response.data;
                });
        },
        methods: {
            deleteProduct(id) { 
                this.axios
                    .delete(`http://localhost:8000/api/products/${id}`)
                    .then(response => {
                        let i = this.products.map(data => data.id).indexOf(id);
                        this.products.splice(i, 1)
                    });
            }
        }
    }
</script>

Create.vue

<template>
  <div>
    <h3 class="text-center">Create Product</h3>
    <div class="row">
      <div class="col-md-12">
        <form @submit.prevent="addProduct">
          <div class="form-group">
            <label>Title</label>
            <input type="text" class="form-control" v-model="product.title" />
          </div>
          <div class="form-group">
            <label>Price</label>
            <input type="text" class="form-control" v-model="product.price" />
          </div>
          <div class="form-group">
            <label>Description</label>
            <input type="text" class="form-control" v-model="product.description" />
          </div>
          <button type="submit" class="btn btn-primary">Create</button>
        </form>
      </div>
    </div>
  </div>
</template>
 
<script>
export default {
  data() {
    return {
      product: {},
    };
  },
  methods: {
    addProduct() {
      this.axios
        .post("http://localhost:8000/api/products", this.product)
        .then((response) => this.$router.push({ name: "home" }))
        .catch((err) => console.log(err))
        .finally(() => (this.loading = false));
    },
  },
};
</script>

Edit.vue

<template>
  <div>
    <h3 class="text-center">Edit Product</h3>
    <div class="row">
      <div class="col-md-6">
        <form @submit.prevent="updateProduct">
          <div class="form-group">
            <label>Title</label>
            <input type="text" class="form-control" v-model="product.title" />
          </div>
          <div class="form-group">
            <label>Price</label>
            <input type="text" class="form-control" v-model="product.price" />
          </div>
          <div class="form-group">
            <label>Description</label>
            <input type="text" class="form-control" v-model="product.description" />
          </div>
          <button type="submit" class="btn btn-primary">Update</button>
        </form>
      </div>
    </div>
  </div>
</template>
 
<script>
export default {
  data() {
    return {
      product: {},
    };
  },
  created() {
    this.axios
      .get(`http://localhost:8000/api/products/${this.$route.params.id}`)
      .then((res) => {
        this.product = res.data;
      });
  },
  methods: {
    updateProduct() {
      this.axios
        .patch(
          `http://localhost:8000/api/products/${this.$route.params.id}`,
          this.product
        )
        .then((res) => {
          this.$router.push({ name: "home" });
        });
    },
  },
};
</script>

Step 9: Create Vue Routes

Go to resources/js/routes.js, create routes.js file and paste this code

import All from './components/All.vue';
import Create from './components/Create.vue';
import Edit from './components/Edit.vue';

export const routes = [{
        name: 'home',
        path: '/',
        component: All
    },
    {
        name: 'create',
        path: '/create',
        component: Create
    },
    {
        name: 'edit',
        path: '/edit/:id',
        component: Edit
    }
];

Step 10: Locate App.vue in app.js

The final step is to define the location of App.vue, it is the most important file in Vue JS to run the Application.

require('./bootstrap');

window.Vue = require('vue').default;

import App from './components/App.vue';
import VueAxios from 'vue-axios';
import VueRouter from 'vue-router';
import axios from 'axios';
import { routes } from './routes';


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

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

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

Screenshots

Source Code in GitHub: https://github.com/ravindrarana/product-management—Laravel-Vue-JS




Copyright © 2020-2021 Engineer Jagat All rights reserved. Developed by Ravindra Rana