CRUD app using Laravel 8 VILT stack (Part 2)

Continuing from the Part 1 we’ll add views to our CRUD app using Vue.js and Inertia.js. For backend development of Model and Controller components of this MVC we used classic Laravel with a bit of sprinkle of Inertia.js in Controller. So, without further ado, let’s do views.

First of all, for the purpose of displaying flash messages in views, let’s change share() function of app/Http/Middleware/HandleInertiaRequests.php as follows:

    public function share(Request $request)
    {
        return array_merge(parent::share($request), [
            'flash' => function () use ($request) {
                return [
                    'success' => $request->session()->get('success'),
                    'error' => $request->session()->get('error'),
                ];
            },
        ]);
    }

Now, create a new folder named ‘Posts‘ in resources/js/Pages/ (be aware of capitalization). Create three new files in ‘Posts‘ folder i.e. Index.vue, Create.vue and Edit.vue (again watch out capitalization).

Insert following code in Index.vue:

<template>
    <app-layout>
        <div v-if="$page.props.flash.success" class="bg-green-600 text-white">
            {{ $page.props.flash.success }}
        </div>
        <div class="m-4">
            <Link class="border bg-indigo-300 rounded-xl px-4 py-2 hover:bg-indigo-600 hover:text-white" :href="route('posts.create')">
                Create
            </Link>        
        </div>
        <div class="">
            <table class="shadow-lg border m-4 rounded-xl">
                <thead>
                    <tr class="bg-indigo-100">
                        <th class="py-2 px-4 border">Title</th>
                        <th class="py-2 px-4 border">Body</th>
                        <th class="py-2 px-4 border">Actions</th>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="item in data" :key="item.id">
                        <td class="py-2 px-4 border">{{item.title}}</td>
                        <td class="py-2 px-4 border">{{item.body}}</td>
                        <td class="py-2 px-4 border">
                            <Link class="border bg-indigo-300 rounded-xl px-4 py-2 m-2 hover:bg-indigo-600 hover:text-white" :href="route('posts.edit', item.id)">
                                Edit
                            </Link>        
                            <button class="border bg-indigo-300 rounded-xl px-4 py-2 m-2 hover:bg-indigo-600 hover:text-white" @click="destroy(item.id)">
                                Delete
                            </button>        
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
    </app-layout>
</template>

<script>
    import AppLayout from '@/Layouts/AppLayout'
    import { Head, Link } from '@inertiajs/inertia-vue3'

 export default {
        components: {
            AppLayout,
            Head,
            Link
        },
        props: ['data'],
        methods: {
        destroy(id) {
            this.$inertia.delete(this.route('posts.destroy', id))
            },        
        },
    }
</script>

Put following code in Create.vue:

<template>
    <app-layout>
        <div class="">
            <form @submit.prevent="submit">
                <div class="p-2 m-4 flex">
		    <div class="m-4">
			<label class="mr-4" for="title">Title:</label>
			<input type="text" v-model="form.title" class="rounded-lg" name="title"/>
			<div v-if="errors.title">{{ errors.title }}</div>
 		    </div>
		    <div class="m-4">
			<label class="mr-4" for="body">Body:</label>
			<input type="text" v-model="form.body" class="rounded-lg" name="body"/>
			<div v-if="errors.body">{{ errors.body }}</div>
                    </div>
                </div>
                <div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex justify-start items-center">
                    <button class="border bg-indigo-300 rounded-xl px-4 py-2 m-4 hover:bg-indigo-600 hover:text-white" type="submit">Create Post</button>
                </div>
            </form>
        </div>
    </app-layout>
</template>

<script>
    import AppLayout from '@/Layouts/AppLayout'

    export default {
        components: {
            AppLayout,
        },

        props: {
            errors : Object    
        },

        data() {
            return {
                form: {
                    title: null,
                    body: null,
                },
            }
        },
        methods: {
            submit() {
            this.$inertia.post(this.route('posts.store'), this.form)
            },
        },
    }
</script>

Insert following code in Edit.vue:

<template>
    <app-layout>
        <div class="">
            <form @submit.prevent="form.put(route('posts.update', post.id))">
                <div class="p-2 m-4 flex">
		    <div class="m-4">
			<label class="mr-4" for="title">Title:</label>
			<input type="text" v-model="form.title" class="rounded-lg" name="title"/>
			<div v-if="errors.title">{{ errors.title }}</div>
		    </div>
		    <div class="m-4">
			<label class="mr-4" for="body">Body:</label>
			<input type="text" v-model="form.body" class="rounded-lg" name="body"/>
			<div v-if="errors.body">{{ errors.body }}</div>
                    </div>
                </div>
                <div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex justify-start items-center">
                    <button class="border bg-indigo-300 rounded-xl px-4 py-2 m-4 hover:bg-indigo-600 hover:text-white" type="submit">Update Post</button>
                </div>
            </form>
        </div>
    </app-layout>
</template>

<script>
    import AppLayout from '@/Layouts/AppLayout'

    export default {
        components: {
            AppLayout,
        },

        props: {
            errors : Object,
            post : Object    
        },

        data() {
            return {
                form: this.$inertia.form({
                    title: this.post.title,
                    body: this.post.body,
                }),
            }
        },
    }
</script>

Finally, execute the following command to compile UI assets:

npm run dev

Run Laravel development server by executing:

php artisan serve

Enter the following URL in your browser to access index of Posts (don’t forget to create a user login first):

localhost:8000/posts

2 thoughts on “CRUD app using Laravel 8 VILT stack (Part 2)”

Leave a Comment