简体   繁体   中英

How to use jQuery to pass value into coffescript ActionCable

I am trying to create dynamic channels for users to chat in, but I am unable to pass the room_id into the App.cable.subscriptions.create call that is in the room.coffee file. Any help in clarifying why I cannot use jQuery to get the value is extremely helpful.

This is what I receive back in the console:

RoomChannel is transmitting the subscription confirmation
RoomChannel is streaming from room__channel

RoomsController

class RoomsController < ApplicationController
  before_action :authenticate_user!

  def show
    other_user = User.find(params[:id])
    title = [other_user.id.to_s, current_user.id.to_s].sort!.join("-")
    @room = Room.where(title: title).first
    if @room.nil?
      @room = Room.create! title: title
    else
      @messages = Message.where(room_id: @room[:id])
    end
  end

end

show.html.erb

<h1>Chat Room</h1>
<div id="messages">
  <% if @messages.blank? %>
    <div id="no_messages_yet">
      <p>No messages yet...</p>
    </div>
  <% else %>
      <%= render @messages %>
  <% end %>
</div>
<form>
  <label>Say something:</label><br>
  <input type="text" data-behavior="room_speaker">
  <input type="hidden" value="<%= @room[:id] %>" id="room_id">
  <input type="hidden" value="<%= current_user[:id] %>" id="user_id">
</form>

views/messages/_message.html.erb

<div class="message">
  <p><%= message.content %></p>
</div>

room.coffee

$(document).ready ->
  room_id = $("#room_id").val()
  console.log(room_id)
  // => 1
  // When I try and pass 'room_id' as the value for room_id:, I get an error stating the variable is not recognized.
App.room = App.cable.subscriptions.create {channel: "RoomChannel", room_id: $('#room_id').val()},
  connected: ->
    # Called when the subscription is ready for use on the server

  disconnected: ->
    # Called when the subscription has been terminated by the server

  received: (data) ->
    $('#messages').append data['message']
    # Called when there's incoming data on the websocket for this channel

  speak: (message, room_id, user_id) ->
    @perform 'speak', message: message, room_id: room_id, user_id: user_id

$(document).on 'keypress', '[data-behavior~=room_speaker]', (event) ->
  if event.keyCode is 13 # return = send
    App.room.speak event.target.value, $('#room_id').val(), $('#user_id').val()
    event.target.value = ""
    event.preventDefault()

RoomChannel

class RoomChannel < ApplicationCable::Channel
  def subscribed
    stream_from "room_#{params[:room_id]}_channel"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end

  def speak(data)
    m = Message.new
    m.user_id = data["user_id"]
    m.room_id = data["room_id"]
    m.content = data["message"]
    m.save!
  end
end

message.rb

class Message < ApplicationRecord
  after_create_commit { MessageBroadcastJob.perform_later self }
end

jobs/message_broadcast_job.rb

class MessageBroadcastJob < ApplicationJob
  queue_as :default

  def perform(message)
    ActionCable.server.broadcast "room_#{message.room_id}_channel", message: render_message(message)
  end

  private
  def render_message(message)
    ApplicationController.renderer.render(partial: 'messages/message', locals: { message: message })
  end
end

Place the functionality inside the $(document).ready call. Remember coffeescript is very touchy when it comes to indentation and whitespace.

$(document).ready ->
  room_id = $('#room_id').val()
  App.room = App.cable.subscriptions.create {channel: "RoomChannel", room_id: room_id},

    connected: ->
      # Called when the subscription is ready for use on the server

    disconnected: ->
      # Called when the subscription has been terminated by the server

    received: (data) ->
      $('#messages').append data['message']
      # Called when there's incoming data on the websocket for this channel

    speak: (message, room_id, user_id) ->
      @perform 'speak', message: message, room_id: room_id, user_id: user_id

$(document).on 'keypress', '[data-behavior~=room_speaker]', (event) ->
  if event.keyCode is 13 # return = send
    App.room.speak event.target.value, $('#room_id').val(), $('#user_id').val()
    event.target.value = ""
    event.preventDefault()

Easiest way would be pass the value into HTML as data attribute. And read that back from CoffeeScript with jQuery.

You can add it to messages div or the form. Something like this:

<div id="messages" data-room-id="<%= params[:id] %>">

And in JavaScript, read it with:

$('#messages').data('room-id')

In vanilla JavaScript:

document.getElementById('messages').dataset.roomId

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM