EDIT: Full code for the 3 most likely files are found here. https://codepen.io/arcticmedia-ryan/project/editor/ZEQwmN
I am not sure how best to explain this so please let me know if you want more. I am building a chat room app. When a person opens up the main vue, they are presented with a "Room List" - from there they can click enter and join the room. The issue is, when they click join, it opens up the tab for the room but doesnt make it active. I feel like I am just banging my head around a simple problem
There is a prop called "SelectedRoomID" that needs to be updated from "undefined" to the room that is selected from the list.
RoomList.vue
<!-- This example requires Tailwind CSS v2.0 -->
<template>
<TransitionRoot as="template" :show="isOpen">
<Dialog as="div" class="fixed z-10 inset-0 overflow-y-auto" @close="$emit('onClose')">
<div class="flex items-end justify-center min-h-screen pt-4 px-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-300" leave-from="opacity-100"
leave-to="opacity-0">
<DialogOverlay class="fixed inset-0 bg-gray-700 bg-opacity-75 transition-opacity"/>
</TransitionChild>
<!-- This element is to trick the browser into centering the modal contents. -->
<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-300"
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 align-bottom bg-black bg-opacity-20 rounded-lg px-6 pt-5 pb-4 text-left overflow-hidden shadow-2xl transform transition-all sm:my-8 sm:align-middle sm:p-6">
<div class="sm:flex sm:items-start">
<div class="flex flex-col">
<div class="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div class="align-middle inline-block min-w-full sm:px-4 lg:px-5">
<div class="shadow overflow-hidden border-8 border-gray-800 dark:border-gray-900 sm:rounded-lg">
<table class="min-w-full divide-y divide-gray-800">
<thead class="bg-gray-800 dark:bg-gray-900">
<tr>
<th scope="col"
class="px-6 py-3 text-left text-s font-medium text-gray-50 uppercase tracking-wider">
Room
</th>
<th scope="col"
class="px-6 py-3 text-left text-s font-medium text-gray-50 uppercase tracking-wider">
Description
</th>
<th scope="col"
class="px-6 py-3 text-left text-s font-medium text-gray-50 uppercase tracking-wider">
Type
</th>
<th scope="col"
class="px-6 py-3 text-left text-s font-medium text-gray-50 uppercase tracking-wider">
Users
</th>
<th scope="col" class="relative px-6 py-3">
<button type="button"
class="bg-white rounded-md text-gray-400 hover:text-gray-500 "
@click="$emit('onClose')">
<div class="hidden sm:block absolute top-0 right-0 pt-4 pr-4">
<span class="sr-only">Close</span>
<XIcon class="top-1 right-1 absolute h-6 w-6 text-gray-50 " aria-hidden="true"/>
</div>
</button>
<span class="sr-only">Enter</span>
</th>
</tr>
</thead>
<tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-300 dark:divide-gray-600">
<tr v-for="room in $store.state.rooms.rooms" :key="room.id">
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="flex-shrink-0 h-10 w-10">
<img class="h-10 w-10 rounded-full" :src="room.image"
alt=""/>
</div>
<div class="ml-4">
<div class="text-md font-medium text-gray-900 dark:text-gray-50">
{{ room.name }}
</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-md text-gray-900 dark:text-gray-50">{{ room.description }}</div>
</td>
<td class="px-2 py-4 whitespace-nowrap">
<span class="px-2 inline-flex text-s leading-5 font-medium rounded-full">
<div v-if="room.is_private === true" class="rounded-full py-1 px-2 bg-red-100 text-red-800 dark:bg-red-800 dark:text-red-100">
<span>Private</span>
</div>
<div v-else-if="room.is_private === false" class="rounded-full py-1 px-2 bg-green-100 text-green-800 dark:bg-green-800 dark:text-green-100">
<span>Public</span>
</div>
<div v-else-if="room.is_private === 'true'" class="rounded-full py-1 px-2 bg-red-100 text-red-800 dark:bg-red-800 dark:text-red-100">
<span>Private</span>
</div>
<div v-else-if="room.is_private === 'false'" class="rounded-full py-1 px-2 bg-green-100 text-green-800 dark:bg-green-800 dark:text-green-100">
<span>Public</span>
</div>
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-center">
<a class="text-md font-medium text-gray-900 dark:text-gray-50">99</a>
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-md font-medium">
<div class="flex rounded-full py-2 px-4 bg-indigo-700 hover:bg-indigo-900">
<a href="#" @click="joinRoom(room)"
class="text-white">Enter</a>
</div>
</td>
</tr>
</tbody>
</table>
<div class="bg-gray-800 dark:bg-gray-900">
<div class="flex justify-end px-4 py-3 text-left text-s font-medium text-gray-50 uppercase tracking-wider">
<span class=" px-2 pt-2 text-xs leading-5 font-semibold rounded-full">
<a href="#">
<div class="flex rounded-full py-1 px-2 bg-green-700 text-green-100 hover:bg-green-800">
<PlusIcon class="h-5 w-5"/><span class="text-sm font-bold pl-0.5">Create Room</span>
</div>
</a>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</TransitionChild>
</div>
</Dialog>
</TransitionRoot>
</template>
<script>
import {Dialog, DialogOverlay, DialogTitle, TransitionChild, TransitionRoot} from '@headlessui/vue'
import {ExclamationIcon, XIcon, PlusIcon} from '@heroicons/vue/outline'
import {types as RoomTypes} from "../../../Store/modules/rooms/rooms.types";
export default {
components: {
Dialog,
DialogOverlay,
DialogTitle,
TransitionChild,
TransitionRoot,
ExclamationIcon,
XIcon,
PlusIcon,
},
props: ['rooms', 'selectedRoomId'],
emits: ['onSelectRoom', 'onLeaveRoom', 'onClose'],
methods: {
joinRoom(room) {
this.$store.dispatch(RoomTypes.JOIN_ROOM, room);
this.selectedRoomId = this.room;
this.$emit('onClose');
}
},
props: {
isOpen: Boolean,
usersCount: Boolean
},
}
</script>
Main.vue SNIPPET OF CODE
<section aria-labelledby="primary-heading"
class="dark:bg-gray-900 min-w-0 flex-1 h-full flex flex-col overflow-hidden lg:order-last">
<room-tabs :selectedRoomId="currentRoom.id" :rooms="joinedRooms"
@onSelectRoom="currentRoom = $event" @onLeaveRoom="leaveRoom($event)"/>
<message-container :messages="messages"
class="h-full pb-2 mb-2 pt-0 mt-0 shadow-md overflow-y-auto"/>
<input-box
:room="currentRoom"
v-on:messagesent="getMessages"
class="dark:bg-gray-800 px-6 pb-6 pt-4 dark:border-t-2 dark:border-gray-600 bottom-0 sticky"
/>
</section>
I know its inside methods: joinRoom that needs to change and I know its wrong where this.selectedRoomId is - I just dont know what I need to change/fix to make it turn the selected room into the active room when you click join.
Any help would be very much appreciated!
CodePudding user response:
Try to emit selected room from joinRoom
method:
this.$emit('roomSelected', room);
then in Main.vue listen to event:
<room-tabs @roomSelected="roomSelected"
and update id:
methods: {
roomSelected(room){
this.currentRoom.id = room.id
}
}
CodePudding user response:
I would use mapState
to effectively watch the value in the store that is being updated by this.$store.dispatch(RoomTypes.JOIN_ROOM, room);
So in a component that needs to know this value:
computed: {
...mapState(['STORE_NAME', 'STORE_VALUE']),
},
and then you should be able to use this.STORE_VALUE
as a dynamically updated value