article

Saturday, September 3, 2022

Laravel 9 vue 3 Todo List - Create Read Update and Delete

Laravel 9 vue 3 Todo List - Create Read Update and Delete

How to install laravel 9

https://tutorial101.blogspot.com/2022/02/how-to-install-laravel-9.html

Connecting our Database

open .env file root directory.

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

Create Model and Migration:
C:\xampp\htdocs\laravel\laravelproject>php artisan make:model Item -m
app/Models/Item.php
laravelproject\database\migrations\create_items_table.php
//laravelproject\database\migrations\create_items_table.php
<?php

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

return new class extends Migration
{
    public function up()
    {
        Schema::create('items', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->boolean("completed")->default(false);
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('items');
    }
};
Database Migration

php artisan migrate

C:\xampp\htdocs\laravel\laravelproject>php artisan migrate
Migration table created successfully.
check database table

Creating Controller
C:\xampp\htdocs\laravel\laravelproject>php artisan make:controller ItemController --resource

app/Http/Controllers/ItemController.php
//app/Http/Controllers/ItemController.php
<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Item;
use Illuminate\Support\Carbon;

class ItemController extends Controller
{
    public function index()
    {
       return Item::orderBy('created_at', 'desc')->get();
    }
    public function store(Request $request)
    {
        $newItem = new Item;
        $newItem->name = $request->item['name'];
        $newItem->save();

        return $newItem;
    }
    public function update(Request $request, $id)
    {
        $existingItem = Item::find($id);  

        if($existingItem){
           $existingItem->completed = $request->item['completed'] ? true : false;
           $existingItem->updated_at = Carbon::now() ;
           $existingItem->save();
           return $existingItem;

        } 
        return "Item not found";
    }
    public function destroy($id)
    {
        $existingItem = Item::find($id);
        if($existingItem){
           $existingItem->delete();
           return "Item deleted";
        }
        return "Item not found";
    }
}
Edit API Routes laravelproject\routes\api.php
//laravelproject\routes\api.php
<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ItemController;

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

Route::get('/items', [ItemController::class, 'index']);
Route::prefix('/item')->group(function(){
    Route::post('/store',[ItemController::class, 'store']);
    Route::put('/{id}' , [ItemController::class, 'update']);
    Route::delete('/{id}', [ItemController::class, 'destroy'] );
});
Run C:\xampp\htdocs\laravel\laravelproject>php artisan serve
Starting Laravel development server: http://127.0.0.1:8000

Check API Results in Postman
https://www.postman.com/downloads/

Headers ( Content-Type : application/json )
POST method : http://127.0.0.1:8000/api/item/store
Get method : http://127.0.0.1:8000/api/items
PUT method : http://127.0.0.1:8000/api/item/1
DELTE method : http://127.0.0.1:8000/api/item/1
Frontend Vue js 3
Install Vue 3

npm install vue@next
npm install
npm i vue-loader
npm run dev

create components folder under resources/assets/js/
create vue file Welcome.vue laravelproject\resources\js\components\Welcome.vue
laravelproject\resources\js\components\Welcome.vue
//laravelproject\resources\js\components\Welcome.vue
<template>
    <div class="container w-100 m-auto text-center mt-3">
        <h1 class="text-danger">Laravel vue todo list</h1>
        <add-item-form v-on:reloadlist="getItems()" />
        <list-view
            :items="items"
            v-on:reloadlist="getItems()"
            class="text-center"
        />
    </div>
</template>
<script>
    import listView from "./listView";
    import addItemForm from "./addItemForm";

    export default {
        components: {
            addItemForm,
            listView
        },

        data: function() {
            return {
                items: []
            };
        },
        methods: {
            getItems() {
                axios
                    .get("api/items")
                    .then(res => {
                        this.items = res.data;
                    })
                    .catch(error => {
                        console.log(error);
                    });
            }
        },
        created() {
            this.getItems();
        }
    };
</script>
open webpack.mix.js root directory and add .vue()
mix.js('resources/js/app.js', 'public/js')
.vue()
Next, Go to resources/assets/js then open app.js file and intialize vue js components in this file.

open app.js file and update the following code into your app.js file:
laravelproject\resources\js\app.js
//laravelproject\resources\js\app.js
import './bootstrap';

import { createApp } from 'vue';
import Welcome from './components/Welcome'
  
const app = createApp({})
  
app.component('welcome', Welcome)
  
app.mount('#app')
Open welcome.blade.php file
laravelproject\resources\view\welcome.blade.php
//laravelproject\resources\view\welcome.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Laravel 9 VUE 3</title>
    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css">
    <link href="{{ mix('css/app.css') }}" rel="stylesheet">
</head>
<body>
       
    <div id="app">
    <div class="card-body">        
        <welcome></welcome>
    </div>
    </div>
    <script src="{{ mix('js/app.js') }}" defer></script>
</body>
</html>
AddItemForm.vue
laravelproject\resources\js\components\AddItemForm.vue
//laravelproject\resources\js\components\AddItemForm.vue
<template>
    <div class="mt-3">
        <h2>add item form</h2>
        <div class="container m-2 w-100">
            <input
                type="test"
                placeholder="add item"
                class="border"
                v-model="item.name"
            />
            <button
                :class="[item.name ? 'active' : 'notactive']"
                @click="addItem()"
            >
                add +
            </button>
        </div>
    </div>
</template>
<script>
export default {
    data: function() {
        return {
            item: {
                name: ""
            }
        };
    },
    methods: {
        addItem() {
            if (this.item.name == "") {
                return;
            }
            axios
                .post("api/item/store", {
                    item: this.item
                })
                .then(res => {
                    if (res.status == 201) {
                        this.item.name = "";
                        this.$emit("reloadlist");
                    }
                })
                .catch(error => {
                    console.log(error);
                });
        }
    }
};
</script>

<style scoped>
.active {
    color: white;
    background-color: blue;
}
.inactive {
    color: gray;
}
</style>
listItem.vue
laravelproject\resources\js\components\listItem.vue
//laravelproject\resources\js\components\listItem.vue
<template>
    <li class="list-group-item d-flex justify-content-between w-50">
        <input
            type="checkbox"
            @change="updateCheck()"
            v-model="item.completed"
            class="mr-3"
        />
        <span :class="[item.completed ? 'completed' : '', 'item']">{{
            item.name
        }}</span>
        <button class="btn-danger ml-3" @click="removeItem()">X</button>
    </li>
</template>

<script>
export default {
    props: ["item"],
    methods: {
        updateCheck() {
            axios
                .put(`api/item/${this.item.id}`, {
                    item: this.item
                })
                .then(res => {
                    if (res.status == 200) {
                        this.$emit("itemchanged");
                    }
                })
                .catch(error => {
                    console.log("error from axios put", errors);
                });
        },
        removeItem() {
            axios
                .delete(`api/item/${this.item.id}`)
                .then(res => {
                    if (res.status == 200) {
                        this.$emit("itemchanged");
                    }
                })
                .catch(error => {
                    console.log("error from axios delte ", error);
                });
        }
    }
};
</script>

<style>
.completed {
    text-decoration: line-through;
    color: gray;
}
.item {
    word-break: break-all;
}
</style>
listView.vue
laravelproject\resources\js\components\listView.vue
//laravelproject\resources\js\components\listView.vue
<template>
    <div class="mt-4">
        <h4>list view</h4>
        <hr class="w-50 m-auto mb-3" />
        <ul class="list-group m-auto">
            <list-item
                :item="item"
                v-on:itemchanged="$emit('reloadlist')"
                v-for="item in items"
                :key="item.id"
                class="m-auto my-1 text-justify text-wrap"
            />
        </ul>
    </div>
</template>

<script>
import listItem from "./listItem";

export default {
    components: {
        listItem
    },
    props: ["items"]
};
</script>
Run Development Server

C:\xampp\htdocs\laravel\laravelproject>npm run dev

C:\xampp\htdocs\laravel\laravelproject>php artisan serve
Starting Laravel development server: http://127.0.0.1:8000

Related Post