Vue Advanced Chat Component
Vue Advanced Chat is a versatile, highly customizable chat rooms component built with Vue.js, but designed to be compatible with any JavaScript framework (Vue, React, Angular) or no framework at all, thanks to its Web Component support. Currently stable at version 2.1.2, it sees regular updates with minor bug fixes and feature enhancements, as evidenced by its consistent monthly or bi-monthly release cadence. Key differentiators include its backend-agnostic design, comprehensive feature set (images, videos, files, voice messages, emojis, message editing, replies, user tagging, text formatting), integrated UI elements for chat states (seen, typing, deleted), and support for online/offline statuses and light/dark themes. It ships with TypeScript types, facilitating robust development, and provides examples for integration with backends like Firestore, demonstrating its flexibility in handling real-time data.
Common errors
-
[Vue warn]: Failed to resolve component: vue-advanced-chat
cause `vue-advanced-chat` is being used as a custom HTML element but is not registered as such in your Vue application's compiler options.fixIn your Vue build configuration (e.g., `vite.config.js` for Vite or `vue.config.js` for Vue CLI), add `isCustomElement: tagName => tagName === 'vue-advanced-chat' || tagName === 'emoji-picker'` within your Vue plugin's `template.compilerOptions`. -
(Component appears unstyled or with broken layout)
cause The core CSS stylesheet for `vue-advanced-chat` has not been imported into your application.fixAdd `import 'vue-advanced-chat/dist/vue-advanced-chat.css';` to your main JavaScript/TypeScript entry file (e.g., `main.js`, `main.ts`) or a global style entry point. -
TypeError: Converting circular structure to JSON
cause You are passing complex JavaScript objects directly to `rooms` or `messages` props, but the component expects these props to be pre-stringified JSON.fixEnsure that the `rooms` and `messages` props are explicitly converted to JSON strings using `JSON.stringify()` before being passed to the component, e.g., `:rooms="JSON.stringify(myRoomsArray)"`. -
Messages or rooms do not display, or sending messages does nothing.
cause The component is backend-agnostic and requires you to implement the logic for fetching and sending messages using its event API. It does not handle data persistence or real-time communication out-of-the-box.fixImplement handlers for events like `@send-message` and `@fetch-messages` to interact with your chosen backend service. Update the component's `messages` and `rooms` props with data retrieved from your backend.
Warnings
- gotcha When using `vue-advanced-chat` within a Vue.js application, it functions as a Web Component. It is crucial to configure your Vue compiler (e.g., in `vite.config.js` or `vue.config.js`) to recognize `vue-advanced-chat` and `emoji-picker` as custom elements. Failing to do so will result in 'Failed to resolve component' errors.
- gotcha The `rooms` and `messages` props on the `<vue-advanced-chat>` component expect stringified JSON arrays, not direct JavaScript objects. Passing raw objects will likely lead to incorrect rendering or runtime errors.
- gotcha The component requires a specific CSS file for its styling. If this stylesheet is not imported, the chat interface will appear unstyled, broken, or not function correctly.
- gotcha Vue Advanced Chat is backend-agnostic, meaning it does not come with built-in real-time communication logic. You must implement your own backend and integrate it using the component's event API (e.g., `@send-message`, `@fetch-messages`).
Install
-
npm install vue-advanced-chat -
yarn add vue-advanced-chat -
pnpm add vue-advanced-chat
Imports
- VueAdvancedChat (as custom element registration)
import { VueAdvancedChat } from 'vue-advanced-chat';import 'vue-advanced-chat';
- CSS Styles
import 'vue-advanced-chat/dist/vue-advanced-chat.css';
- TypeScript Types
import { ChatMessage } from 'vue-advanced-chat';import type { ChatMessage, Room, User } from 'vue-advanced-chat/dist/types';
Quickstart
/* vite.config.ts */
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [
vue({
template: {
compilerOptions: {
// Crucial for Vue to recognize vue-advanced-chat and emoji-picker as custom elements
isCustomElement: tagName => tagName === 'vue-advanced-chat' || tagName === 'emoji-picker'
}
}
})
]
});
/* main.ts or main.js */
import { createApp } from 'vue';
import App from './App.vue';
import 'vue-advanced-chat/dist/vue-advanced-chat.css'; // Essential styles
import 'vue-advanced-chat'; // Registers the custom Web Components
const app = createApp(App);
app.mount('#app');
/* App.vue */
<template>
<div id="app-container">
<vue-advanced-chat
height="100vh"
:current-user-id="currentUserId"
:rooms="JSON.stringify(rooms)"
:rooms-loaded="true"
:messages="JSON.stringify(messages)"
:messages-loaded="true"
@send-message="handleSendMessage"
@fetch-messages="handleFetchMessages"
/>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
// For type safety, if using TypeScript
// import type { ChatMessage, Room } from 'vue-advanced-chat/dist/types';
const currentUserId = 'user1';
const rooms = ref([
{
roomId: 'room1',
roomName: 'General Chat',
avatar: 'https://via.placeholder.com/150',
users: [
{ _id: 'user1', username: 'Alice' },
{ _id: 'user2', username: 'Bob' }
],
lastMessage: { content: 'Hello everyone!', senderId: 'user2', timestamp: Date.now() }
},
{
roomId: 'room2',
roomName: 'Private Discussion',
users: [
{ _id: 'user1', username: 'Alice' },
{ _id: 'user3', username: 'Charlie' }
],
lastMessage: { content: 'Meeting at 3 PM?', senderId: 'user3', timestamp: Date.now() }
}
]);
const messages = ref([
{
_id: 'msg1',
content: 'Hi there!',
senderId: 'user1',
timestamp: Date.now() - 60000
},
{
_id: 'msg2',
content: 'Hello Alice!',
senderId: 'user2',
timestamp: Date.now() - 30000
},
{
_id: 'msg3',
content: 'How are you two?',
senderId: 'user1',
timestamp: Date.now() - 10000
}
]);
const handleSendMessage = ({ detail }: any) => {
const { roomId, content, files, replyMessage } = detail; // 'detail' contains the event payload
console.log('New message:', { roomId, content, files, replyMessage });
messages.value.push({
_id: `msg${Date.now()}`,
content: content,
senderId: currentUserId,
timestamp: Date.now()
});
// In a real app, send this message to your backend
};
const handleFetchMessages = ({ detail }: any) => {
const { room, options } = detail;
console.log('Fetching messages for room:', room.roomId, options);
// Simulate async fetch for older messages
setTimeout(() => {
// Add logic to load historical messages based on 'options.reset' or 'options.direction'
}, 500);
};
</script>
<style>
body, html, #app {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden; /* Important for full-height chat layout */
}
#app-container {
height: 100vh;
width: 100vw;
}
</style>