Search code examples
vuejs3vue-props

Vue 3 props are not passed to the child element


I'm trying to pass an object to a child element as a prop, but I get an arr[0] val instead of { id: 1, name: 'General' }.

There I bind prop value, currentRoom is a const with Object.

<input-message :currentRoom="currentRoom"/>

currentRooms value is correct there and equals {id: 1, name: 'General'}.

In child element I try to get props that way:

const props = defineProps({
  currentRoom: Object
});

The whole code:

container.vue

<template>
    <AppLayout title="Dashboard">
        <template #header>
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">
                Chat
            </h2>
        </template>

        <div class="py-12">
            <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
                <div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
                    <message-container :room="currentRoom"/>
                    <input-message :currentRoom="currentRoom" :customText="'blablabla'"/>
                </div>
            </div>
        </div>
    </AppLayout>
</template>

<script setup>
import AppLayout from '../../Layouts/AppLayout.vue';
import MessageContainer from "./messageContainer.vue";
import InputMessage from "./inputMessage.vue";
import {defineComponent} from "vue";

defineComponent([
    AppLayout,
    MessageContainer,
    InputMessage
])

let chatRooms = [];
let currentRoom = [];
let messages = [];

const getRooms = () => {
    axios.get('/chat/rooms')
    .then( response => {
        chatRooms = response.data;
        setRoom(response.data[0]);
    })
    .catch(error => {
        console.log(error);
    })
}

const setRoom = (room) => {
    currentRoom = room;
    // If I console.log currentRoom here, it is displayed correctly!
    console.log(currentRoom)
    getMessages();
}

const getMessages = () => {
    axios.get('/chat/rooms/' + currentRoom.id + '/messages')
    .then(response => {
        messages = response.data;
    })
    .catch(error => {
        console.log(error);
    });
}

getRooms();
</script>

inputMessage.vue

<template>
    <div class="relative h-10 m-1">
        <div style="border-top: 1px solid #e6e6e6;" class="grid grid-cols-6">
            <input
                type="text"
                v-model="message"
                @keyup.enter="sendMessage"
                placeholder="Say something..."
                class="col-span-5 outline-none p-1"
            />
            <button
                @click="sendMessage"
                class="place-self-end bg-gray-500 hover:bg-blue-700 p-1 mt-1 rounded text-white">
                Send
            </button>
        </div>
    </div>
</template>

<script setup>
const props = defineProps({
    currentRoom: Object
    // customText: Text
});

console.log(props.currentRoom);
</script>

Solution

  • Just do it right way and it will work.

    const { createApp, ref } = Vue;
    
    const MyComponent = {
      props: {
        currentRoom : {
          type: Object,
          default: {}
        }
      },  
      setup(props) {
        console.log(`props.currentRoom: ${JSON.stringify(props.currentRoom)}`)
      },
      template: `<div class="MyComponent">currentRoom: {{JSON.stringify(currentRoom)}}</div>`   
    }
    
    const App = {
      components: {
        MyComponent
      },
      setup() {  
        const rooms = ref([]);   
        const addRoom = () => { rooms.value.push( {id: rooms.value.length + 1, name: 'General'} ); }    
        return { rooms, addRoom }
      }
    }
    
    const app = createApp(App)
    app.mount('#app')
    .MyComponent {
      border: 1px solid grey;
      padding: 12px;
      margin: 4px;
    }
    <div id="app">  
      App.rooms: {{rooms}}<hr/>
        rooms[0]: <my-component :current-room="rooms[0]"></my-component>
        rooms: <my-component v-for="room in rooms" :current-room="room"></my-component>
      <button type="button" @click="addRoom()">Add Room</button>
    </div>
    <script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>