'Vue component not implementing in laravel project?

I am trying to get my vue component to render the messages from my database in laravel blade file and it is not rendering for some reason. I am using this Github repo https://github.com/kevilondo/group-chat, as an example to implement into my project. Now it is submitting to the database as I can see the data in the database and it is posting well, but the messages are not showing.

I have very limited experience in vue js by the way.

The error I am getting in the console is Uncaught TypeError: Cannot read properties of undefined (reading 'prototype').

This is what my app.js file looks like:

import Alpine from "alpinejs";

window.Alpine = Alpine;

const { default: axios } = require('axios');
const { default: Echo } = require('laravel-echo');
require('./bootstrap');

Alpine.start();
window.Vue = require('vue');

Vue.prototype.$userId = document.querySelector("meta[name='user-id']").getAttribute('content');
import VueChatScroll from 'vue-chat-scroll'

Vue.use(VueChatScroll)
Vue.component('message', require('./components/message.vue').default);


const app = new Vue({
    el: '#app',
    mounted(){

        //we assign the value of this to this variable in order to access the value of chat inside data inside our http request
        var vm = this

        //we get the group id in the url
        const url = window.location.href;
        const groupId = url.split("/").slice(-1)[0];
        vm.groupId = groupId;

        axios.get('/show_messages/' + groupId)
            .then(res => {
                //push every message one by one
                res.data.messages.map(message => {
                    vm.chat.push(message)
                    //console.log(vm);
                });
            })
            .catch(error => {
                console.log(error)
            })

        window.Echo.private('message-channel')
            .listen('MessageEvent', (e) => {
                vm.chat.push(e.message)
            });
    },
    data: {
        message: '',
        groupId: null,
        chat: [

        ],
    },
    methods: {
        send_message (event) {
            event.preventDefault();

            let token = document.head.querySelector('meta[name="csrf-token"]');

            axios.post('/send_message/'+ this.groupId, {message: this.message}, {'X-CSRF-TOKEN': token})
                .then(res => {
                    this.message = ''
                })
                .catch(error => {
                    console.log(error)
                })
        }
    }

});

This is what the bootstrap file looks like:

window._ = require('lodash');

try {
    window.Popper = require('popper.js').default;
    window.$ = window.jQuery = require('jquery');
    require('bootstrap');
} catch (e) {}

window.axios = require('axios');

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

import Echo from 'laravel-echo';

window.Pusher = require('pusher-js');

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: process.env.MIX_PUSHER_APP_KEY,
    cluster: process.env.MIX_PUSHER_APP_CLUSTER,
    forceTLS: true
});

This is what the Message.vue looks like:

<template>
  <div v-if="user_id !== this.$userId" class="container card bg-info mb-4 float-start" style="width: 58%;">
    <p>{{message}}</p>

    <p> <span class="text-danger">{{name}}</span> <small>{{formatDate}}</small></p>
  </div>

  <div v-else class="container card bg-default mb-4 float-end" style="width: 58%;">
    <p>{{message}}</p>
    <p> <span class="text-danger">You</span> <small>{{formatDate}}</small></p>
  </div>
</template>

<script>
export default {
  props: ['user_id', 'userLoggedIn', 'name', 'message', 'created_at'],
  mounted() {
    //
  },
  computed: {
    formatDate(){
      //we convert the text into a date

      let dateAndTime = new Date(this.created_at);

      let year = dateAndTime.getFullYear();

      let months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'];

      let month = months[dateAndTime.getMonth()];

      let day = dateAndTime.getDate();

      let time = dateAndTime.getHours() + ':' + dateAndTime.getMinutes();

      return `${day}  ${month}  ${year}  ${time}`

    }
  }
}
</script>

Relevant part of show.blade.php:

 <div class="card-body container">
                    <div class="message-container mb-5" id="message-container" style="overflow-y: scroll; height:400px;" v-chat-scroll>
                        <message v-for="(message, id) in chat "
                        v-bind:key="id"
                        v-bind:message = "message.message"
                        v-bind:name = "message.user.name"
                        v-bind:user_id = "message.user.id"
                        v-bind:created_at = "message.created_at"
                        >
                        </message>
                    </div>

                    <form action="/send_message/{{$group->id}}" method="post" v-on:submit='send_message'>
                        @csrf

                        <textarea name="message" id="message" v-model="message" class="col-md-12 form-control @error('message') is-invalid @enderror" cols="20" rows="5"></textarea>
                        @error('message')
                            <span class="invalid-feedback" role="alert">
                                <strong>{{$message}}</strong>
                            </span>
                        @enderror
                        <button class="btn btn-primary" type="submit">Send message</button>
                    </form>

app.blade.php file:

 <body class="font-sans antialiased">
    <div id="app">

    <div class="min-h-screen bg-gray-100">
            @include('layouts.navigation')

            <!-- Page Heading -->
            <header class="bg-white shadow">
                <div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
                </div>
            </header>

            <!-- Page Content -->
            <main>
                @yield('content')


            </main>
        </div>
{{--    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>--}}
</div>
<script src="{{asset('js/bootstrap.js')}}"></script>
<script src="{{asset('js/app.js')}}"></script>
</body>

Controller method :

public function show_messages($id)
    {
        $group = Group::find($id);

        $messages = $group->group_messages()->with(['group', 'user'])->get();

        $user_loggedIn = auth()->user();

        return ['messages' => $messages, 'user_loggedIn' => $user_loggedIn];
    }


Solution 1:[1]

I found some error on console. You can do the following to clear it

  • On app.js file import Vue from default

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

  • On app.blade.php remove import bootstrap.js because already used on app.js

    {{-- Remove next line --}}
    <script src="{{asset('js/bootstrap.js')}}"></script> 

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

  • On MessageController.php update show_messages method to be

public function show_messages($id)
    {
        $group = Group::find($id);

        $messages = $group->messages()->with(['group', 'user'])->get();

        $user_loggedIn = auth()->user();

        return ['messages' => $messages, 'user_loggedIn' => $user_loggedIn];
    }

Solution 2:[2]

I think this line from the GitHub repo is creating the problem as it is only available when the user is logged in.

@if (!Auth::guest())
        <meta name="user-id" content="{{ Auth::user()->id }}">
@endif

If the user isn't always logged in, you can use optional like:

<meta name="user-id" content="{{ optional(Auth::user())->id }}">

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Suhail Kawsara
Solution 2 Shrey