Installations
npm install actioncable-vue
Developer Guide
Typescript
Yes
Module System
CommonJS
Node Version
22.7.0
NPM Version
10.8.2
Score
78.6
Supply Chain
100
Quality
80.5
Maintenance
100
Vulnerability
100
License
Releases
Unable to fetch releases
Contributors
Unable to fetch Contributors
Languages
JavaScript (100%)
Love this project? Help keep it running — sponsor us today! 🚀
Developer
mclintprojects
Download Statistics
Total Downloads
1,683,520
Last Day
177
Last Week
5,394
Last Month
22,789
Last Year
330,098
GitHub Statistics
MIT License
184 Stars
290 Commits
37 Forks
4 Watchers
1 Branches
10 Contributors
Updated on Feb 17, 2025
Package Meta Information
Latest Version
3.1.0
Package Id
actioncable-vue@3.1.0
Unpacked Size
39.18 kB
Size
11.10 kB
File Count
7
NPM Version
10.8.2
Node Version
22.7.0
Published on
Dec 14, 2024
Total Downloads
Cumulative downloads
Total Downloads
1,683,520
Last Day
-8.8%
177
Compared to previous day
Last Week
6.8%
5,394
Compared to previous week
Last Month
22.1%
22,789
Compared to previous month
Last Year
-15.5%
330,098
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
ActionCableVue is an easy-to-use Action Cable integration for VueJS.
🚀 Installation
1npm install actioncable-vue --save
1// Vue 3.x 2import { createApp } from "vue"; 3import App from "./App.vue"; 4import ActionCableVue from "actioncable-vue"; 5 6const actionCableVueOptions = { 7 debug: true, 8 debugLevel: "error", 9 connectionUrl: "ws://localhost:5000/api/cable", // If you don"t provide a connectionUrl, ActionCable will use the default behavior 10 connectImmediately: true, 11 unsubscribeOnUnmount: true, 12}; 13 14createApp(App) 15 .use(store) 16 .use(router) 17 .use(ActionCableVue, actionCableVueOptions) 18 .mount("#app");
1// Vue 2.x 2import Vue from "vue"; 3import ActionCableVue from "actioncable-vue"; 4import App from "./App.vue"; 5 6Vue.use(ActionCableVue, { 7 debug: true, 8 debugLevel: "error", 9 connectionUrl: "ws://localhost:5000/api/cable", // or function which returns a string with your JWT appended to your server URL as a query parameter 10 connectImmediately: true, 11}); 12 13new Vue({ 14 router, 15 store, 16 render: (h) => h(App), 17}).$mount("#app");
Parameters | Type | Default | Required | Description |
---|---|---|---|---|
debug | Boolean | false | Optional | Enable logging for debug |
debugLevel | String | error | Optional | Debug level required for logging. Either info , error , or all |
connectionUrl | String/Function | null | Optional | ActionCable websocket server url. Omit it for the default behavior |
connectImmediately | Boolean | true | Optional | ActionCable connects to your server immediately. If false, ActionCable connects on the first subscription. |
unsubscribeOnUnmount | Boolean | true | Optional | Unsubscribe from channels when component is unmounted. |
store | Object | null | Optional | Vuex store |
Table of content
- Component Level Usage
- Subscriptions
- Unsubscriptions
- Manually connect to the server
- Disconnecting from the server
- Performing an action on your Action Cable server
- Usage with Vuex
- Usage with Nuxt.JS
Wall of Appreciation
- Many thanks to @x88BitRain for adding Vue 3 compatibility
🌈 Component Level Usage
If you want to listen to channel events from your Vue component:
- If you're using Vue 3
setup
script define achannels
object in thesetup
function. - If you're using Vue 3
defineComponent
define achannels
property. - You need to either add a
channels
object in the Vue component (Vue 2 only) - If you're using
vue-class-component
define achannels
property. (Vue 2 only)
Each defined object in channels
will start to receive events provided you subscribe correctly.
1. Vue 3 setup
script
1<script setup> 2import { onMounted, onUnmounted } from "vue"; 3 4const channels = { 5 ChatChannel: { 6 connected() { 7 console.log("connected"); 8 }, 9 }, 10}; 11 12onMounted(() => { 13 this.$cable.registerChannels(channels); 14 this.$cable.subscribe({ 15 channel: "ChatChannel", 16 }); 17}); 18 19onUnmounted(() => { 20 this.$cable.unregisterChannels(channels); 21 this.$cable.unsubscribe("ChatChannel"); 22}); 23</script>
2. Vue 3 defineComponent
1import { onMounted } from "vue"; 2 3export default defineComponent({ 4 channels: { 5 ChatChannel: { 6 connected() { 7 console.log("connected"); 8 }, 9 rejected() { 10 console.log("rejected"); 11 }, 12 received(data) {}, 13 disconnected() {}, 14 }, 15 }, 16 setup() { 17 onMounted(() => { 18 this.$cable.subscribe({ 19 channel: "ChatChannel", 20 }); 21 }); 22 }, 23});
3. Vue 2.x.
1new Vue({ 2 data() { 3 return { 4 message: "Hello world", 5 }; 6 }, 7 channels: { 8 ChatChannel: { 9 connected() {}, 10 rejected() {}, 11 received(data) {}, 12 disconnected() {}, 13 }, 14 }, 15 methods: { 16 sendMessage: function () { 17 this.$cable.perform({ 18 channel: "ChatChannel", 19 action: "send_message", 20 data: { 21 content: this.message, 22 }, 23 }); 24 }, 25 }, 26 mounted() { 27 this.$cable.subscribe({ 28 channel: "ChatChannel", 29 room: "public", 30 }); 31 }, 32});
4. Vue 2.x vue-class-component
1@Component 2export default class ChatComponent extends Vue { 3 @Prop({ required: true }) private id!: string; 4 5 get channels() { 6 return { 7 ChatChannel: { 8 connected() { 9 console.log("connected"); 10 }, 11 rejected() {}, 12 received(data) {}, 13 disconnected() {}, 14 }, 15 }; 16 } 17 18 sendMessage() { 19 this.$cable.perform({ 20 channel: "ChatChannel", 21 action: "send_message", 22 data: { 23 content: this.message, 24 }, 25 }); 26 } 27 28 async mounted() { 29 this.$cable.subscribe({ 30 channel: "ChatChannel", 31 room: "public", 32 }); 33 } 34}
👂🏾 Subscriptions
1. Subscribing to a channel
Define a channels
object in your component matching the action cable server channel name you passed for the subscription.
1<script setup> 2import { onMounted } from "vue"; 3 4const channels = { 5 ChatChannel: { 6 connected() { 7 console.log("connected"); 8 }, 9 }, 10}; 11 12onMounted(() => { 13 this.$cable.registerChannels(channels); 14 this.$cable.subscribe({ 15 channel: "ChatChannel", 16 }); 17}); 18</script>
Important ⚠️
ActionCableVue automatically uses your ActionCable server channel name if you do not pass in a specific channel name to use in your
channels
. It will also override clashing channel names.
2. Subscribing to the same channel but different rooms
1<script setup> 2import { onMounted } from "vue"; 3 4const channels = { 5 chat_channel_public: { 6 connected() { 7 console.log("I am connected to the public chat channel."); 8 }, 9 }, 10 chat_channel_private: { 11 connected() { 12 console.log("I am connected to the private chat channel."); 13 }, 14 }, 15}; 16 17onMounted(() => { 18 this.$cable.registerChannels(channels); 19 20 this.$cable.subscribe( 21 { 22 channel: "ChatChannel", 23 room: "public" 24 }, 25 "chat_channel_public" 26 ); 27 28 this.$cable.subscribe( 29 { 30 channel: "ChatChannel", 31 room: "private" 32 }, 33 "chat_channel_private" 34 ); 35}); 36</script>
3. Subscribing to a channel with a computed name
1// Conversations.vue 2 3<script setup> 4import { onMounted } from "vue"; 5const router = useRouter(); 6 7const openConversation = (conversationId) => { 8 router.push({name: "conversation", params: {id: conversationId}); 9} 10</script>
1// Chat.vue 2 3<script setup> 4import { onMounted } from "vue"; 5const route = useRoute(); 6 7const channels = { 8 computed: [ 9 { 10 channelName() { 11 return `chat-convo-${route.params.conversationId}`; 12 }, 13 connected() { 14 console.log("I am connected to a channel with a computed name."); 15 }, 16 rejected() {}, 17 received(data) {}, 18 disconnected() {}, 19 }, 20 ], 21} 22 23onMounted(() => { 24 this.$cable.registerChannels(channels); 25 this.$cable.subscribe({ 26 channel: `chat-convo-${route.params.conversationId}`, 27 }); 28}); 29</script>
🔇 Unsubscriptions
For Vue 2.x and when using Vue 3.x
defineComponent
, when your component is destroyed ActionCableVue automatically unsubscribes from any channel that component was subscribed to.
1. Unsubscribing from a channel (Vue 3.x setup script)
1<script setup> 2import {onUnmounted } from "vue"; 3onUnmounted(() => { 4 this.$cable.unsubscribe("ChatChannel"); 5}); 6</script>
2. Unsubscribing from a channel Vue 2.x
1new Vue({ 2 methods: { 3 unsubscribe() { 4 this.$cable.unsubscribe("ChatChannel"); 5 }, 6 }, 7});
🔌 Manually connect to the server
ActionCableVue automatically connects to your Action Cable server if connectImmediately
is not set to false
during setup. If you do set connectImmediately
to false
you can manually trigger a connection to your ActionCable server with this.$cable.connection.connect
.
1<script setup> 2const connectWithRefreshedToken = (token) => { 3 this.$cable.connection.connect(`ws://localhost:5000/api/cable?token=${token}`); 4} 5</script>
✂️ Disconnecting from the server
1<script setup> 2const disconnect = () => { 3 this.$cable.connection.disconnect(); 4} 5</script>
💎 Performing an action on your Action Cable server
Requires that you have a method defined in your Rails Action Cable channel whose name matches the action property passed in.
1<script setup> 2import { onMounted } from "vue"; 3 4const sendMessage = () => { 5 this.$cable.perform({ 6 channel: "ChatChannel", 7 action: "send_message", 8 data: { 9 content: "Hi", 10 }, 11 }); 12}; 13 14const channels = { 15 ChatChannel: { 16 connected() { 17 console.log("Connected to the chat channel"); 18 }, 19 received(data) { 20 console.log("Message received"); 21 }, 22 }, 23}; 24 25onMounted(() => { 26 this.$cable.registerChannels(channels); 27 this.$cable.subscribe({ 28 channel: "ChatChannel", 29 }); 30}); 31</script>
🐬 Usage with Vuex (Vue 2.x)
ActionCableVue has support for Vuex. All you have to do is setup your store correctly and pass it in during the ActionCableVue plugin setup.
1// store.js 2 3import Vue from "vue"; 4import Vuex from "vuex"; 5 6Vue.use(Vuex); 7 8export default new Vuex.Store({ 9 state: {}, 10 mutations: { 11 sendMessage(state, content) { 12 this.$cable.perform({ 13 action: "send_message", 14 data: { 15 content, 16 }, 17 }); 18 }, 19 }, 20 actions: { 21 sendMessage({ commit }, content) { 22 commit("sendMessage", content); 23 }, 24 }, 25});
1import store from "./store"; 2import Vue from "vue"; 3import ActionCableVue from "actioncable-vue"; 4 5Vue.use(ActionCableVue, { 6 debug: true, 7 debugLevel: "all", 8 connectionUrl: process.env.WEBSOCKET_HOST, 9 connectImmediately: true, 10 store, 11});
💪 Usage with Nuxt
ActionCableVue works just fine with Nuxt 2 or 3. All you need to do is set it up as a client side plugin.
Nuxt 3
1// /plugins/actioncablevue.client.js 2import ActionCableVue from "actioncable-vue"; 3 4export default defineNuxtPlugin(({ vueApp }) => { 5 const config = useRuntimeConfig(); 6 7 vueApp.use(ActionCableVue, { 8 debug: true, 9 debugLevel: "all", 10 connectionUrl: config.public.WEBSOCKET_HOST, 11 connectImmediately: true, 12 }); 13}); 14 15 16// /pages/chat.vue 17<script setup> 18const { vueApp } = useNuxtApp(); 19 20let $cable; 21const channels = { 22 ChatChannel: { 23 connected() { 24 console.log("connected"); 25 }, 26 } 27}; 28 29onMounted(() => { 30 $cable = vueApp.config.globalProperties.$cable; 31 32 $cable.registerChannels(channels, vueApp); 33 $cable.subscribe({ 34 channel: "ChatChannel", 35 }); 36}); 37 38onUnmounted(() => { 39 $cable.unregisterChannels(channels, vueApp); 40 $cable.unsubscribe("ChatChannel"); 41}); 42</script>
Nuxt 2
1// /plugins/actioncable-vue.js 2 3import Vue from "vue"; 4import ActionCableVue from "actioncable-vue"; 5 6if (process.client) { 7 Vue.use(ActionCableVue, { 8 debug: true, 9 debugLevel: "all", 10 connectionUrl: process.env.WEBSOCKET_HOST, 11 connectImmediately: true, 12 }); 13} 14 15// nuxt.config.js 16plugins: [{ src: "@/plugins/actioncable-vue", ssr: false }];

No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
- Info: project has a license file: LICENSE:0
- Info: FSF or OSI recognized license: MIT License: LICENSE:0
Reason
0 existing vulnerabilities detected
Reason
6 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 5
Reason
detected GitHub workflow tokens with excessive permissions
Details
- Warn: no topLevel permission defined: .github/workflows/test.yml:1
- Info: no jobLevel write permissions found
Reason
Found 0/16 approved changesets -- score normalized to 0
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/mclintprojects/actioncable-vue/test.yml/master?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/mclintprojects/actioncable-vue/test.yml/master?enable=pin
- Info: 0 out of 1 GitHub-owned GitHubAction dependencies pinned
- Info: 0 out of 1 third-party GitHubAction dependencies pinned
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
- Warn: no security policy file detected
- Warn: no security file to analyze
- Warn: no security file to analyze
- Warn: no security file to analyze
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Reason
branch protection not enabled on development/release branches
Details
- Warn: branch protection not enabled for branch 'master'
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
- Warn: 0 commits out of 15 are checked with a SAST tool
Score
3.9
/10
Last Scanned on 2025-02-10
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More