diff --git a/README.md b/README.md index 2f7eca4..b108130 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ - +
ActionCableVue is an easy-to-use Action Cable integration for VueJS.
@@ -19,26 +19,6 @@ npm install actioncable-vue --save ``` -```javascript -// Vue 2.x -import Vue from "vue"; -import ActionCableVue from "actioncable-vue"; -import App from "./App.vue"; - -Vue.use(ActionCableVue, { - debug: true, - debugLevel: "error", - connectionUrl: "ws://localhost:5000/api/cable", // or function which returns a string with your JWT appended to your server URL as a query parameter - connectImmediately: true, -}); - -new Vue({ - router, - store, - render: (h) => h(App), -}).$mount("#app"); -``` - ```javascript // Vue 3.x import { createApp } from "vue"; @@ -48,7 +28,7 @@ import ActionCableVue from "actioncable-vue"; const actionCableVueOptions = { debug: true, debugLevel: "error", - connectionUrl: "ws://localhost:5000/api/cable", + connectionUrl: "ws://localhost:5000/api/cable", // If you don"t provide a connectionUrl, ActionCable will use the default behavior connectImmediately: true, unsubscribeOnUnmount: true, }; @@ -60,8 +40,28 @@ createApp(App) .mount("#app"); ``` +```javascript +// Vue 2.x +import Vue from "vue"; +import ActionCableVue from "actioncable-vue"; +import App from "./App.vue"; + +Vue.use(ActionCableVue, { + debug: true, + debugLevel: "error", + connectionUrl: "ws://localhost:5000/api/cable", // or function which returns a string with your JWT appended to your server URL as a query parameter + connectImmediately: true, +}); + +new Vue({ + router, + store, + render: (h) => h(App), +}).$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](https://guides.rubyonrails.org/action_cable_overview.html#connect-consumer) | @@ -71,7 +71,6 @@ createApp(App) #### Table of content -- [Support ActionCable-Vue](https://github.com/mclintprojects/actioncable-vue#-support-actioncable-vue) - [Component Level Usage](https://github.com/mclintprojects/actioncable-vue#-component-level-usage) - [Subscriptions](https://github.com/mclintprojects/actioncable-vue#-subscriptions) - [Unsubscriptions](https://github.com/mclintprojects/actioncable-vue#-unsubscriptions) @@ -85,19 +84,75 @@ createApp(App) - Many thanks to [@x88BitRain](https://github.com/x8BitRain) for adding Vue 3 compatibility -#### ☕ Support ActionCable-Vue - -If you'd like to donate to support the continued development and maintenance of actioncable-vue, you can do so [here.](https://sendcash.africa/#/send/NG/2001944264/50211) - #### 🌈 Component Level Usage If you want to listen to channel events from your Vue component: -1. You need to either add a `channels` object in the Vue component -2. If you're using `vue-class-component` define a `channels` property. -3. If you're using Vue 3 `defineComponent` define a `channels` property. + +1. If you're using **Vue 3** `setup` script define a `channels` object in the `setup` function. +2. If you're using **Vue 3** `defineComponent` define a `channels` property. +3. You need to either add a `channels` object in the Vue component **(Vue 2 only)** +4. If you're using `vue-class-component` define a `channels` property. **(Vue 2 only)** Each defined object in `channels` will start to receive events provided you subscribe correctly. +##### 1. Vue 3 `setup` script + +```typescript + +``` + +##### 2. Vue 3 `defineComponent` + +```typescript +import { onMounted } from "vue"; + +export default defineComponent({ + channels: { + ChatChannel: { + connected() { + console.log("connected"); + }, + rejected() { + console.log("rejected"); + }, + received(data) {}, + disconnected() {}, + }, + }, + setup() { + onMounted(() => { + this.$cable.subscribe({ + channel: "ChatChannel", + }); + }); + }, +}); +``` + +##### 3. Vue 2.x. + ```javascript new Vue({ data() { @@ -133,7 +188,7 @@ new Vue({ }); ``` -Alternative definition for `vue-class-component` users. +##### 4. Vue 2.x `vue-class-component` ```typescript @Component @@ -172,140 +227,141 @@ export default class ChatComponent extends Vue { } ``` -Alternative definition for Vue 3 `defineComponent` users. - -```typescript -import { onMounted } from 'vue'; - -export default defineComponent({ - channels: { - ChatChannel: { - connected() { - console.log('connected'); - }, - rejected() { - console.log('rejected'); - }, - received(data) {}, - disconnected() {}, - }, - }, - setup() { - onMounted(() => { - this.$cable.subscribe({ - channel: "ChatChannel", - }); - }); - }, -}); -``` - -#### ✨ Subscriptions +#### 👂🏾 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. -```javascript -new Vue({ - channels: { - ChatChannel: { - connected() { - console.log("I am connected."); - }, +```typescript + ``` -##### Important +### 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 -```javascript -new Vue({ - channels: { - chat_channel_public: { - connected() { - console.log("I am connected to the public chat channel."); - }, - }, - chat_channel_private: { - connected() { - console.log("I am connected to the private chat channel."); - }, +```typescript + ``` ###### 3. Subscribing to a channel with a computed name -```javascript +```typescript // Conversations.vue -new Vue({ - methods: { - openConversation(conversationId){ - this.$router.push({name: 'conversation', params: {id: conversationId}); - } - } -}); + ``` -```javascript +```typescript // Chat.vue -new Vue({ - channels: { - computed: [ - { - channelName() { - return `${this.$route.params.conversationId}`; - }, - connected() { - console.log("I am connected to a channel with a computed name."); - }, - rejected() {}, - received(data) {}, - disconnected() {}, + ``` -#### 🎃 Unsubscriptions +#### 🔇 Unsubscriptions -> When your component is **destroyed** ActionCableVue **automatically unsubscribes** from any channel **that component** was subscribed to. +> 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) + +```typescript + +``` + +###### 2. Unsubscribing from a channel Vue 2.x ```javascript new Vue({ @@ -314,81 +370,70 @@ new Vue({ this.$cable.unsubscribe("ChatChannel"); }, }, - mounted() { - this.$cable.subscribe({ - channel: "ChatChannel", - }); - }, }); ``` -#### 👺 Manually connect to the server +#### 🔌 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`. -```javascript -new Vue({ - methods: { - connectWithRefreshedToken(token) { - // You can optionally pass in a connection URL string - // You can optionally pass in a function that returns a connection URL - // You can choose not to pass in anything and it'll reconnect with the connection URL provided during setup. - this.$cable.connection.connect( - `ws://localhost:5000/api/cable?token=${token}`, - ); - }, - }, -}); +```typescript + ``` -#### 👽 Disconnecting from the server +#### ✂️ Disconnecting from the server -```javascript -new Vue({ - methods: { - disconnect() { - this.$cable.connection.disconnect(); - }, - }, -}); +```typescript + ``` #### 💎 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. -```javascript -new Vue({ - channels: { - ChatChannel: { - connected() { - console.log("Connected to the chat channel"); - }, - received(data) { - console.log("Message received"); - }, +```typescript + ``` -#### 🐬 Usage with Vuex +#### 🐬 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. @@ -434,9 +479,58 @@ Vue.use(ActionCableVue, { }); ``` -#### 💪 Usage with Nuxt.JS +#### 💪 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 + +```javascript +// /plugins/actioncablevue.client.js +import ActionCableVue from "actioncable-vue"; + +export default defineNuxtPlugin(({ vueApp }) => { + const config = useRuntimeConfig(); + + vueApp.use(ActionCableVue, { + debug: true, + debugLevel: "all", + connectionUrl: config.public.WEBSOCKET_HOST, + connectImmediately: true, + }); +}); + + +// /pages/chat.vue + +``` -ActionCableVue works just fine with Nuxt.JS. All you need to do is set it up as a client side plugin. +##### Nuxt 2 ```javascript // /plugins/actioncable-vue.js @@ -452,14 +546,7 @@ if (process.client) { connectImmediately: true, }); } -``` -Don't forget to register your plugin. - -```javascript // nuxt.config.js -/* - ** Plugins to load before mounting the App - */ plugins: [{ src: "@/plugins/actioncable-vue", ssr: false }]; ```