Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Alodon's avatar

[Vue warn]: Error in render: "TypeError: Cannot read property 'smAndDown' of undefined"

I am getting this error in my console log. Please help me.

0 likes
13 replies
wingly's avatar

Post the problematic code so we can help you

Alodon's avatar

I have three components. this is PrivateChat.vue

<template>
  <v-layout row>
    <v-flex class="online-users" xs3>
      <v-list>
          <v-list-tile
            v-for="friend in friends"
            :color="(friend.id==activeFriend)?'green':''"
            :key="friend.id"
            @click="activeFriend=friend.id"
          >
            <v-list-tile-action>
              <v-icon :color="(onlineFriends.find(user=>user.id===friend.id))?'green':'red'">account_circle</v-icon>
            </v-list-tile-action>

            <v-list-tile-content>
              <v-list-tile-title>{{friend.name}}</v-list-tile-title>
            </v-list-tile-content>

            <!-- <v-list-tile-avatar>
              <img :src="item.avatar">
            </v-list-tile-avatar> -->
          </v-list-tile>


        </v-list>

    </v-flex>
    
    <v-flex id="privateMessageBox" class="messages mb-5" xs9>
        <message-list :user="user" :all-messages="allMessages"></message-list>

        <div class="floating-div">
            <picker v-if="emoStatus" set="emojione" @select="onInput" title="Pick your emoji…" />

        </div>

        <v-footer
                height="auto"
                fixed
                color="grey"
        >
            <v-layout row >
                <v-flex class="ml-2 text-right" xs1>
                    <v-btn @click="toggleEmo" fab dark small color="pink">
                        <v-icon>insert_emoticon </v-icon>
                    </v-btn>
                </v-flex>

                <v-flex xs1 class="text-center">
                    <file-upload
                            :post-action="'/user/private-messages/'+activeFriend"
                            ref='upload'
                            v-model="files"
                            @input-file="$refs.upload.active = true"
                            :headers="{'X-CSRF-TOKEN': token}"
                    >
                        <v-icon class="mt-3">attach_file</v-icon>
                    </file-upload>

                </v-flex>
                <v-flex xs6 >
                    <v-text-field
                            rows=2
                            v-model="message"
                            label="Enter Message"
                            single-line
                            @keyup.enter="sendMessage"
                    ></v-text-field>
                </v-flex>

                <v-flex xs4>
                    <v-btn
                            @click="sendMessage"
                            dark class="mt-3 ml-2 white--text" small color="green">send</v-btn>


                </v-flex>

            </v-layout>


        </v-footer>


    </v-flex>

  </v-layout>
</template>

<script>
  import MessageList from './_message-list'
  import { Picker } from 'emoji-mart-vue'


  export default {
    props:['user'],
    components:{
      Picker,
      MessageList
    },
    
    data () {
      return {
        message:null,
        files:[],
        activeFriend:null,
        typingFriend:{},
        onlineFriends:[],
        allMessages:[],
        typingClock:null,
        emoStatus:false,
        users:[],
        token:document.head.querySelector('meta[name="csrf-token"]').content

      }
    },

    computed:{
      friends(){
        return this.users.filter((user)=>{
          return user.id !==this.user.id;
        })
      }
    },

    watch:{
      files:{
        deep:true,
        handler(){
          let success=this.files[0].success;
          if(success){
            this.fetchMessages();
          }
        }
      },
      activeFriend(val){
        this.fetchMessages();
      },
      '$refs.upload'(val){
        console.log(val);
      }
    },

    methods:{
      onTyping(){
        Echo.private('privatechat.'+this.activeFriend).whisper('typing',{
          user:this.user

        });
      },
      sendMessage(){

        //check if there message
        if(!this.message){
          return alert('Please enter message');
        }
        if(!this.activeFriend){
          return alert('Please select friend');
        }

          axios.post('/private-messages/'+this.activeFriend, {message: this.message}).then(response => {
                    this.message=null;
                    this.allMessages.push(response.data.message)
                    setTimeout(this.scrollToEnd,100);
          });
      },
      fetchMessages() {
         if(!this.activeFriend){
          return alert('Please select friend');
        }
            axios.get('/private-messages/'+this.activeFriend).then(response => {
                this.allMessages = response.data;
              setTimeout(this.scrollToEnd,100);

            });
        },
      fetchUsers() {
            axios.get('/users').then(response => {
                this.users = response.data;
                if(this.friends.length>0){
                  this.activeFriend=this.friends[0].id;
                }
            });
        },


      scrollToEnd(){
        document.getElementById('privateMessageBox').scrollTo(0,99999);
      },
      toggleEmo(){
        this.emoStatus= !this.emoStatus;
      },
      onInput(e){
        if(!e){
          return false;
        }
        if(!this.message){
          this.message=e.native;
        }else{
          this.message=this.message + e.native;
        }
        this.emoStatus=false;
      },

      onResponse(e){
        console.log('onrespnse file up',e);
      }

    
    },

    mounted(){
    },

    created(){
              this.fetchUsers();

              Echo.join('plchat')
              .here((users) => {
                   console.log('online',users);
                   this.onlineFriends=users;
              })
              .joining((user) => {
                  this.onlineFriends.push(user);
                  console.log('joining',user.name);
              })
              .leaving((user) => {
                  this.onlineFriends.splice(this.onlineFriends.indexOf(user),1);
                  console.log('leaving',user.name);
              });
             
              Echo.private('privatechat.'+this.user.id)
                .listen('PrivateMessageSent',(e)=>{
                  console.log('pmessage sent')
                  this.activeFriend=e.message.user_id;
                  this.allMessages.push(e.message)
                  setTimeout(this.scrollToEnd,100);

              })
              .listenForWhisper('typing', (e) => {

                  if(e.user.id==this.activeFriend){

                      this.typingFriend=e.user;
                      
                    if(this.typingClock) clearTimeout();

                      this.typingClock=setTimeout(()=>{
                                            this.typingFriend={};
                                        },9000);
                  }


                 
            });

    }
    
  }
</script>

<style scoped>

.online-users,.messages{
  overflow-y:scroll;
  height:100vh;
}

</style>

Chat.vue

<template>
  <v-layout row>
    <v-flex xs12 sm6 offset-sm3>
      <v-card class="chat-card" >

        <v-list>
          <v-subheader
            >
              Group Chat
            </v-subheader>
            <v-divider></v-divider>

            <message-list :user="user" :all-messages="allMessages"></message-list>
        </v-list>
      </v-card>

    </v-flex>

      <div class="floating-div">
          <picker v-if="emoStatus" set="emojione" @select="onInput" title="Pick your emoji…" />

      </div>

      <v-footer
      height="auto"
      fixed
      color="grey"
      >
      <v-layout row >
          <v-flex class="ml-2 text-right" xs1>
              <v-btn @click="toggleEmo" fab dark small color="pink">
                  <v-icon>insert_emoticon </v-icon>
              </v-btn>
          </v-flex>

          <v-flex xs1 class="text-center">
             <file-upload
             post-action="/messages"
             ref='upload'
             @input-file="$refs.upload.active = true"
             :headers="{'X-CSRF-TOKEN': token}"
             >
                 <v-icon class="mt-3">attach_file</v-icon>
             </file-upload>

        </v-flex>
        <v-flex xs6 >
            <v-text-field
              rows=2
              v-model="message"
              label="Enter Message"
              single-line
              @keyup.enter="sendMessage"
            ></v-text-field>
        </v-flex>

        <v-flex xs4>
            <v-btn
              @click="sendMessage"
             dark class="mt-3 ml-2 white--text" small color="green">send</v-btn>


        </v-flex>

      </v-layout>


    </v-footer>
  </v-layout>
</template>

<script>
  import { Picker } from 'emoji-mart-vue'
  import MessageList from './_message-list'
  export default {
    props:['user'],
    components:{
      Picker,
      MessageList
    },
    
    data () {
      return {
        message:null,
        emoStatus:false,
        myText:null,
        allMessages:[],
        token:document.head.querySelector('meta[name="csrf-token"]').content
      }
    },

    methods:{
      sendMessage(){

        //check if there message
        if(!this.message){
          return alert('Please enter message');
        }

          axios.post('/messages', {message: this.message}).then(response => {
                    this.message=null;
                    this.emoStatus=false;
                    this.allMessages.push(response.data.message)
                    setTimeout(this.scrollToEnd,100);
          });
      },
      fetchMessages() {
            axios.get('/messages').then(response => {
                this.allMessages = response.data;

            });
        },

      scrollToEnd(){
        window.scrollTo(0,99999);
      },
      onInput(e){
        if(!e){
          return false;
        }
        if(!this.message){
          this.message=e.native;
        }else{
          this.message=this.message + e.native;
        }
      },
      toggleEmo(){
            this.emoStatus= !this.emoStatus;
      }

    },

    mounted(){
    },

    created(){
      this.fetchMessages();

      Echo.private('lchat')
      .listen('MessageSent',(e)=>{
          this.allMessages.push(e.message)
          setTimeout(this.scrollToEnd,100);

      });

    }
    
  }
</script>

<style scoped>
.chat-card{
  margin-bottom:140px;
}
.floating-div{
    position: fixed;
}
.chat-card img {
    max-width: 300px;
    max-height: 200px;
}

</style>

_message-list.vue

<template>
  <div>
      <v-list
              class="p-3"
              v-for="(message, index) in allMessages"
              :key="index"
      >
          <div class="message-wrapper">
              <v-flex>
                  <span class="small font-italic">{{message.user.name}}</span>
              </v-flex>





              <div v-if="message.message" class="text-message-container">
                  <v-chip :color="(user.id===message.user_id)?'green':'red'" text-color="white">
                      {{message.message}}

                  </v-chip>

              </div>

              <div class="image-container">
                  <img v-if="message.image"  :src="'/storage/'+message.image" alt="">

              </div>

              <v-flex class="caption font-italic">
                  {{message.created_at}}
              </v-flex>
          </div>


      </v-list>

  </div>
</template>

<script>
  export default {
    props:['user','allMessages'],

  }
</script>

<style scoped>
.chat-card{
  margin-bottom:140px;
}
.floating-div{
    position: fixed;
}
.chat-card img {
    max-width: 300px;
    max-height: 200px;
}

</style>

wingly's avatar

Seems like you are using vuetify is this installed correctly ?

Alodon's avatar

I have installed vuetify but not sure if it's installed correctly.

wingly's avatar

Can you verify the installation for example in you blade file where you have you base element v-app if you remove everything else do you still get errors ?

Alodon's avatar

Ok, I tried. But getting the error after deleting clearing components code.

wingly's avatar

Can you show me the contents of your app.js located inside resources folder ?

Alodon's avatar

/**
 * First we will load all of this project's JavaScript dependencies which
 * includes Vue and other libraries. It is a great starting point when
 * building robust, powerful web applications using Vue and Laravel.
 */

require('./bootstrap');

window.Vue = require('vue');

import Vue from 'vue'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'

Vue.use(Vuetify)

const opts = {}

export default new Vuetify(opts)

/**
 * Next, we will create a fresh Vue application instance and attach it to
 * the page. Then, you may begin adding components to this application
 * or customize the JavaScript scaffolding to fit your unique needs.
 */

const VueUploadComponent = require('vue-upload-component')
Vue.component('file-upload', VueUploadComponent)

Vue.component('example-component', require('./components/ExampleComponent.vue'));
Vue.component('Chat', require('./components/Chat.vue'));
Vue.component('PrivateChat', require('./components/PrivateChat.vue'));

const app = new Vue({
    el: '#app'
});

wingly's avatar

Instead of doing export default new Vuetify(opts) can you try to change your code at the end of the file like that

const app = new Vue({
    el: '#app',
   vuetify: new Vuetify(),
});
Alodon's avatar

I can see the old problem is solved. I am able to see the view. But getting this errors. How can I solve them

app.js:50561 [Vue warn]: Unknown custom element: <v-toolbar-side-icon> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

(found in <Root>)
[Vuetify] [BREAKING] 'flat' has been removed, use 'text' instead. For more information, see the upgrade guide https://github.com/vuetifyjs/vuetify/releases/tag/v2.0.0#user-content-upgrade-guide

found in

---> <VBtn>
       <VToolbar>
         <Root>
app.js:50561 [Vue warn]: Failed to mount component: template or render function not defined.

found in

---> <PrivateChat>
       <Root>
wingly's avatar

Did this thing ever worked ? Seems like you are using components that don't exist my guess is they used to exist in older version of vuetify...

Alodon's avatar

I didn't saw any components view but I saw the HTML view that I used in my laravel view. Actually, This is an old code done by someone. But now I am trying to update and use in my project.

wingly's avatar

Read the upgrade guide from vuetify 1 to 2 probably that's your issue

Please or to participate in this conversation.