Actions
Clase 5 de 8 • Curso de Vue.js: Manejo del Estado con Pinia
Contenido del curso
Clase 5 de 8 • Curso de Vue.js: Manejo del Estado con Pinia
Contenido del curso
Ameth Ordoñez Erazo
Ana Selene Zarate Lopez
Julian David Alzate Cuervo
kenedy carlos de la torre mendoza
Diana Martinez
Camilo Acosta
Rene Linares
Diana Martinez
Lavinia Manzanarez
Lavinia Manzanarez
Axlin Miranda
SANTIAGO OCHOA
Felix Torres Javier Antonio
Uriel Solis Salinas
Felix Torres Javier Antonio
Diego Fernando Leyton Ledesma
Ruben Gallegos Hernandez
Para lograr enviar un mensaje presionando la tecla Enter, pueden hacer lo siguiente: En MessagesView.vue, el footer lo deje igual, solo agregando un v-on con el evento keyUp:
<footer> <textarea rows="3" v-model="newMessage" @keyup.enter="sendMessage" ></textarea> <button @click="sendMessage"> <Icon icon="carbon:send-alt" /> </button> </footer>
La función sendMessage queda así:
const sendMessage = () => { addMessage({ message: newMessage.value, channelId: channelId.value, }); newMessage.value = ""; scrollToBottom(); };
Y addMessage es una actions (función) en messages.js:
const addMessage = (newMessage) => { messages.value.push({ id: Date.now(), author: 1, message: newMessage.message, timestamp: new Date().toLocaleTimeString(), read: false, channelId: parseInt(newMessage.channelId), }); };
Profesora Diana logre hacer el reto!! comparto mi solución En channels.js añadi este getter => { const profileStore = useProfileStore() return [ { id: profileStore.id, name: profileStore.username, avatar: profileStore.avatar }, ...state.contacts ] }
para usarlo dentro del componente MesaagesView.vue
lo use de la siguiente manera:
const allContacts = computed(() => contactsStore.getAllContacts) <div class="people-list"> <div class="people-item" v-for="p in allContacts" :key="p.id" > <img :src="p.avatar" :alt="p.name" /> </div> </div>
Hola👋🏻 No me queda algo claro: Por qué para acceder al state dentro del mismo modulo para los getters pasamos el state por parámetro sin embargo para los actions accedemos a través del contexto this? Funcionaría la misma lógica, solo que al revés? Es decir, usar this dentro de un getter para acceder al state y en el caso de los actions pasar el state como un parámetro?
Esta es una aplicación de ejemplo, lo que te haga más sentido, si funciona, está bien.
Este es el getter que agregué en el stor de channels:
getChannelTitle: (state) => (channelId) => { return state.channels.find((channel) => channel.id == channelId).name ?? 'No channel name'; }
La parte de los mensajes no me estaba funcionando, en caso de que se encuentren con algo parecido. Lo resolví forzando el valor a tipo numero. En MessagesView.vue:
channelId.value = Number(id);
Saludos, comparto mi solución:
En el store de channels le anexe en el getter:
getChannelById: (state) => (channelId) => { return state.channels.find(channel => channel.id === channelId) } ```En el store de messages le anexe en el getter: ```js getCountContact: (state) => (channelId) => { const contactStore = useContactStore(); return state.messages.filter(message => message.channelId === channelId) .map(message => { const user = contactStore.getContactById(message.author) return { ...user } }) } ```En el archivo MessageView: ```js watch( () => route.params.id, (id) => { channelId.value = Number(id); scrollToBottom(); const channel = channelStore.getChannelById(channelId.value); if (channel) { title.value = channel.name; people.value = messageStore.getCountContact(channelId.value); } }, { immediate: true } );
mi codigo para mostrar los contactos de una conversacion
const contactsView = computed(() => messagesView.value.reduce((acc, currentValue) => { if (!acc?.includes(currentValue.author.id)) { acc.push(currentValue.author.id) } return acc; }, []) .map(author_id => contactsStore.getContactById(author_id)));
Agregué el mismo watch que estaba en la vista de mensajes, para cambiar los titulos del header dinamicamente.
Respecto a los retos, yo así los solucioné: .
// MessagesView.js // Función para ver los avatares de los contactos que están en el canal const contactsView = computed(() => { const contacts = messagesView.value.map((message) => message.author); // Se obtienen los contactos que enviaron mensajes en el canal return contacts.filter((contact, index) => { // Se filtran los contactos para que no se repitan // contact => Contacto actual // index => Índice del contacto actual return contacts.findIndex((c) => c.id === contact.id) === index; // Se retorna el índice del primer contacto que coincida con el actual }); }); // En el template: <div class="people-item" v-for="contact in contactsView" :key="contact.id" > <img :src="contact.avatar" :alt="contact.name" /> </div>
const updateTitle = () => { const channel = channelsStore.channels.find( (channel) => channel.id === channelId.value ); // Se obtiene el canal actual if (channel) { title.value = channel.name; // Se actualiza el nombre del canal } else { title.value = "Nombre del canal"; } }; watch( // Cuando cambia el ID del canal actual, se actualizan los datos del canal. () => route.params.id, (id) => { channelId.value = parseInt(id); // Se actualiza el ID del canal actual scrollToBottom(); updateTitle(); }, { immediate: true } );
Cualquier duda me pueden preguntar!!
No me la compliqué y para mostrar los contactos, solo agregué un array de canales en el store de contactos.
cree un componente de contactos y solo mostré las fotos.
contacts: [ { id: 1, name: "Tú", avatar: "/avatars/avatar.jpeg", channels:[1,4,5] }, { id: 2, name: "Jason", avatar: "/avatars/avatar-02.jpg", channels:[1,4]}, { id: 3, name: "Janet", avatar: "/avatars/avatar-03.jpg", channels:[1,2]}, ],
Hermano una pregunta, ¿Cómo hiciste para ubicar los avatars en el extremo superior derecho?, yo lo intenté asignándole un space-beetwen al contenedor padre mas cercano, pero al estar la etiqueta img dentro de un bucle se ve de esta manera
Para el nombre del chat creé un getter dentro de channels.js que recibe el channelId, busca por el id y luego retorna solo el nombre.
getters:{ getTitleChannel : (state) => (channelId) => state.channels.find((channel) => channel.id === channelId).name, }
En lo de las imágenes no sabía como quitar los duplicados que obtenía al listar cada autor de la lista de mensajes. Así que me puse a investigar y encontré una solución con filter y findIndex y así pude quitar los duplicados. Este código lo agregé dentro de contacts.js
getters:{ getContactsByChannelId : (state) => (channelId) =>{ const messagesStore = useMessagesStore(); return messagesStore.findMessagesByChannelId(channelId) .map((message)=>{ return state.getContactById(message.author) }) .filter((contact,index,listContacts)=>{ return index == listContacts.findIndex((elementList)=>{ return elementList.id ==contact.id }) }) }, }
Igual cualquier sugerencia es recibida ya que sigo aprendiendo Js 😄