TypeError: undefined is not an object (evaluating ‘props.collection.id’)

  breeze, inertiajs, javascript, laravel, vue.js

It’s a Laravel Breeze project with InertiaJs & VueJs.
In my show.vue page (of a franchise) I can create a collection and in there I can create books for that collection. Anyway, when I create a collection everything is fine, but when I want to create a book, I have this typeError..

And I don’t understand why is it working in the submitCollection function but not in the submitBook function.

Here is the code of my show.vue:

<template>
    <breeze-authenticated-layout>

        <!-- modal create collection -->
        <TransitionRoot as="template" :show="modalCreateCollection">
            <Dialog as="div" static class="fixed inset-0 z-10 overflow-y-auto" @close="modalCreateCollection = false" :open="modalCreateCollection">
                <div class="flex items-end justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
                    <TransitionChild as="template" enter="ease-out duration-300" enter-from="opacity-0" enter-to="opacity-100" leave="ease-in duration-200" leave-from="opacity-100" leave-to="opacity-0">
                        <DialogOverlay class="fixed inset-0 transition-opacity bg-gray-500 bg-opacity-75" />
                    </TransitionChild>
                    <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
                    <TransitionChild as="template" enter="ease-out duration-300" enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" enter-to="opacity-100 translate-y-0 sm:scale-100" leave="ease-in duration-200" leave-from="opacity-100 translate-y-0 sm:scale-100" leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
                        <div class="inline-block px-4 pt-5 pb-4 overflow-hidden text-left align-bottom transition-all transform bg-white rounded-lg shadow-xl sm:my-8 sm:align-middle sm:max-w-sm sm:w-full sm:p-6">
                            <form class="space-y-5">
                                <div>
                                    <label for="email" class="block text-sm font-medium text-gray-700">
                                        Name
                                    </label>
                                    <div class="mt-1">
                                    <input v-model="form.name" type="text" class="block w-full px-3 py-2 placeholder-gray-400 border border-gray-300 rounded-md shadow-sm appearance-none focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" />
                                    </div>
                                </div>
                                <div class="pt-4">
                                    <button @click.prevent="submitCollection" class="flex justify-center w-full px-4 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent rounded-md shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
                                        Add this collection
                                    </button>
                                </div>
                            </form>
                        </div>
                    </TransitionChild>
                </div>
            </Dialog>
        </TransitionRoot>

        <!-- modal edit collection -->
        <TransitionRoot as="template" :show="modalEditCollection">
            <Dialog as="div" static class="fixed inset-0 z-10 overflow-y-auto" @close="modalEditCollection = false" :open="modalEditCollection">
                <div class="flex items-end justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
                    <TransitionChild as="template" enter="ease-out duration-300" enter-from="opacity-0" enter-to="opacity-100" leave="ease-in duration-200" leave-from="opacity-100" leave-to="opacity-0">
                        <DialogOverlay class="fixed inset-0 transition-opacity bg-gray-500 bg-opacity-75" />
                    </TransitionChild>
                    <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
                    <TransitionChild as="template" enter="ease-out duration-300" enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" enter-to="opacity-100 translate-y-0 sm:scale-100" leave="ease-in duration-200" leave-from="opacity-100 translate-y-0 sm:scale-100" leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
                        <div class="inline-block px-4 pt-5 pb-4 overflow-hidden text-left align-bottom transition-all transform bg-white rounded-lg shadow-xl sm:my-8 sm:align-middle sm:max-w-sm sm:w-full sm:p-6">
                            <form class="space-y-5">
                                <div>
                                    <label for="email" class="block text-sm font-medium text-gray-700">
                                        Name
                                    </label>
                                    <div class="mt-1">
                                        <input v-model="form.name" type="text" class="block w-full px-3 py-2 placeholder-gray-400 border border-gray-300 rounded-md shadow-sm appearance-none focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" />
                                    </div>
                                </div>
                                <div class="flex pt-4 space-x-4">
                                    <button @click.prevent="updateCollection" class="flex justify-center w-full px-4 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent rounded-md shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
                                        Update this collection
                                    </button>
                                    <button @click.prevent="destroyCollection" class="flex justify-center px-4 py-2 text-sm font-medium text-white bg-red-500 border border-transparent rounded-md shadow-sm hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-400">
                                        <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5" viewBox="0 0 20 20" fill="currentColor">
                                            <path fill-rule="evenodd" d="M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd" />
                                        </svg>
                                    </button>
                                </div>
                            </form>
                        </div>
                    </TransitionChild>
                </div>
            </Dialog>
        </TransitionRoot>

        <!-- modal create book in collection -->
        <TransitionRoot as="template" :show="modalCreateBook">
            <Dialog as="div" static class="fixed inset-0 z-10 overflow-y-auto" @close="modalCreateBook = false" :open="modalCreateBook">
                <div class="flex items-end justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
                    <TransitionChild as="template" enter="ease-out duration-300" enter-from="opacity-0" enter-to="opacity-100" leave="ease-in duration-200" leave-from="opacity-100" leave-to="opacity-0">
                        <DialogOverlay class="fixed inset-0 transition-opacity bg-gray-500 bg-opacity-75" />
                    </TransitionChild>
                    <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
                    <TransitionChild as="template" enter="ease-out duration-300" enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" enter-to="opacity-100 translate-y-0 sm:scale-100" leave="ease-in duration-200" leave-from="opacity-100 translate-y-0 sm:scale-100" leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
                        <div class="inline-block px-4 pt-5 pb-4 overflow-hidden text-left align-bottom transition-all transform bg-white rounded-lg shadow-xl sm:my-8 sm:align-middle sm:max-w-sm sm:w-full sm:p-6">
                            <form class="space-y-5">
                                <h3 class="text-center uppercase">Add a book in this collection</h3>
                                <div>
                                    <label for="email" class="block text-sm font-medium text-gray-700">
                                        Name
                                    </label>
                                    <div class="mt-1">
                                    <input v-model="form.name" type="text" class="block w-full px-3 py-2 placeholder-gray-400 border border-gray-300 rounded-md shadow-sm appearance-none focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" />
                                    </div>
                                </div>
                                <div>
                                    <label for="password" class="block text-sm font-medium text-gray-700">
                                        Cover
                                    </label>
                                    <div class="mt-1">
                                        <input v-model="form.src" type="text" class="block w-full px-3 py-2 placeholder-gray-400 border border-gray-300 rounded-md shadow-sm appearance-none focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" />
                                    </div>
                                </div>
                                <div class="pt-4">
                                    <button @click.prevent="submitBook" class="flex justify-center w-full px-4 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent rounded-md shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
                                        Add this book
                                    </button>
                                </div>
                            </form>
                        </div>
                    </TransitionChild>
                </div>
            </Dialog>
        </TransitionRoot>

        <template #header>
            <h2 class="text-xl font-semibold leading-tight text-gray-800">
                {{ franchise.name.charAt(0).toUpperCase() + franchise.name.slice(1) }}
            </h2>
            <breeze-button @click="openModalCreateCollection" class="float-right">
                Add a collection
            </breeze-button>
        </template>

        <div v-if="franchise.collections.length >= 1">
            <ul class="space-y-6">
                <li v-for="(collection, index) in franchise.collections" :key="index" >
                    <div class="p-4 space-y-4 bg-white rounded-lg shadow-lg">
                        <div class="flex items-center justify-between">
                            <h3 class="font-semibold">
                                {{ collection.name }}
                            </h3>
                            <div class="flex items-center space-x-6">
                                <button @click="openModalCreateBook">
                                    <svg class="w-6 h-6 text-gray-700 hover:opacity-75" viewBox="0 0 20 20" fill="currentColor">
                                        <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-11a1 1 0 10-2 0v2H7a1 1 0 100 2h2v2a1 1 0 102 0v-2h2a1 1 0 100-2h-2V7z" clip-rule="evenodd" />
                                    </svg>
                                </button>
                                <button @click="openModalEditCollection(collection)">
                                    <svg class="w-6 h-6 text-gray-700 hover:opacity-75" viewBox="0 0 20 20" fill="currentColor">
                                        <path d="M17.414 2.586a2 2 0 00-2.828 0L7 10.172V13h2.828l7.586-7.586a2 2 0 000-2.828z" />
                                        <path fill-rule="evenodd" d="M2 6a2 2 0 012-2h4a1 1 0 010 2H4v10h10v-4a1 1 0 112 0v4a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" clip-rule="evenodd" />
                                    </svg>
                                </button>
                            </div>
                        </div>

                        <div v-if="collection.books.length >= 1">
                            <ul class="grid grid-cols-2 gap-x-4 gap-y-8 sm:grid-cols-3 sm:gap-x-6 lg:grid-cols-4 xl:gap-x-8">
                                <li v-for="(book, index) in collection.books" :key="index">
                                    <div class="block h-full overflow-hidden bg-gray-100 rounded-md shadow cursor-pointer hover:opacity-75 aspect-w-10 aspect-h-7 focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-offset-gray-100 focus-within:ring-indigo-500">
                                        <img :src="book.src" alt="cover" class="object-cover w-full pointer-events-none h-96" />
                                        <p class="block px-2 py-1 text-sm font-medium text-white truncate bg-black pointer-events-none">
                                            {{ book.title.charAt(0).toUpperCase() + book.title.slice(1) }}
                                        </p>
                                    </div>
                                </li>
                            </ul>
                        </div>
                    </div>
                </li>
            </ul>
        </div>
        <div v-else>
            Create your first <span class="font-bold">{{ franchise.name.charAt(0).toUpperCase() + franchise.name.slice(1) }}</span> collection here.
        </div>

    </breeze-authenticated-layout>
</template>
<script>
import BreezeAuthenticatedLayout from '@/Layouts/Authenticated'
import BreezeButton from '@/Components/Button'
import { Dialog, DialogOverlay, DialogTitle, TransitionChild, TransitionRoot } from '@headlessui/vue'
import { ref } from 'vue'
import { Inertia } from '@inertiajs/inertia'

export default {
    name: "franchises-show",
    components: {
        BreezeAuthenticatedLayout,
        BreezeButton,
        Dialog,
        DialogOverlay,
        DialogTitle,
        TransitionChild,
        TransitionRoot,
    },
    props: {
        franchise: Object
    },
    setup (props) {
        const modalCreateCollection = ref(false)
        const modalEditCollection = ref(false)
        const modalCreateBook = ref(false)
        const form = {}

        function updateCollection() {
            Inertia.patch(route('collections.update', {
                collection: this.form.id
            }), this.form)
            this.modalEditCollection = false
        }

        function submitCollection() {
            this.form.franchise = props.franchise.id
            Inertia.post(route('collections.store'), this.form)
            this.form = {}
            this.modalCreateCollection = false
        }

        function destroyCollection() {
            Inertia.delete(route('collections.destroy', {
                collection: this.form.id
            }), this.form)
            this.modalEditCollection = false
        }

        function submitBook() {
            this.form.collection = props.collection.id
            Inertia.post(route('books.store'), this.form)
            this.form = {}
            this.modalCreateBook = false
        }

        return {
            modalCreateCollection,
            modalEditCollection,
            modalCreateBook,
            form,
            submitCollection,
            updateCollection,
            destroyCollection,
            submitBook
        }
    },
    methods: {
        openModalCreateCollection() {
            this.modalCreateCollection = true;
        },
        openModalEditCollection(collection) {
            this.modalEditCollection = true;
            this.form = collection;
        },
        openModalCreateBook() {
            this.modalCreateBook = true;
        }
    }
}
</script>

Source: Laravel

Leave a Reply