I am unable to add typing indicator in my rails app with action cable I have created app in rails 7 and I user trubo stream tag and broadcast in it so I did't used channel for live chat , I tried to find tutorial and video but there is not any
I want to add typing indicator so I writtern js for the same on input it will called and it will go to controller On input I am calling controller "rtm"
room controller
def rtm
@typing = "hhhhhhhhhhhhhhhhhhh"
# ActionCable.server.broadcast "typing_channel",{ message: "helloo"}
# @typings.broadcast_append_to "typing"
Turbo::StreamsChannel.broadcast_append_to "typing", target: 'typing', partial: 'rooms/typing', locals: { message: "@typing" }
end
here I have issue how can I broadcast the typing message to my room page
Room.rb
class Room < ApplicationRecord
scope :public_rooms, -> { where(is_private: false) }
has_many :messages
after_create_commit {broadcast_append_to "rooms"}
end
message.rb
class Message < ApplicationRecord
belongs_to :user
belongs_to :room
after_create_commit { broadcast_append_to self.room }
end
rooms/index
<script>
$(document).ready(function(){
var tmo = null;
$("#msg").on("input", function(){
$.ajax({
type: 'GET',
url: '/rooms/rtm',
data: {data: ''}
});
document.getElementById("typing").innerHTML = "Typing...";
if (tmo) {
clearTimeout(tmo);
}
tmo = setTimeout(function () {
$.ajax({
type: 'GET',
url: '/rooms/rmm',
data: {data: ''}
});
document.getElementById("typing").innerHTML = "";
}, 1000);
});
});
</script>
<div class="container">
<h5> Hi <%= current_user&.firstname %> </h5>
<%= debug(params) if Rails.env.development? %>
<br> <h4> Rooms </h4>
<%= render partial: 'layouts/new_room_form' %>
<%= turbo_stream_from "rooms" %>
<div id="rooms">
<%= render @rooms %>
</div>
</div>
<% if @single_room.present? %>
<%= link_to @single_room.name,@single_room, class: "btn btn-primary" %>
<%= turbo_stream_from @single_room %>
<div id="messages">
<%= render @messages %>
</div>
<%= render partial: 'layouts/new_message_form' %>
<%= @typing %>
<%= turbo_stream_from @typing %>
<div id="typing">
</div>
<%= render partial: 'rooms/typing' %>
<span id="typing"></span><br>
<% end %>
To get the typing indicator you need to use action cable and create a channel for it. You can use turbo stream to render the typing indicator. Example:
app/channels/typing_channel.rb
class TypingChannel < ApplicationCable::Channel
def subscribed
stream_from "typing_channel"
end
end
app/javascript/channels/typing_channel.js
import consumer from "./consumer"
consumer.subscriptions.create("TypingChannel", {
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) {
// Called when there's incoming data on the websocket for this channel
}
});
app/views/rooms/index.html.erb
<div id="typing">
<%= turbo_stream_from "typing_channel" %>
</div>
app/views/rooms/_typing.html.erb
<p><%= message %></p>
app/controllers/rooms_controller.rb
class RoomsController < ApplicationController
def rtm
ActionCable.server.broadcast "typing_channel", { message: "helloo" }
end
end
app/javascript/controllers/rooms_controller.js
import { Controller } from "stimulus"
import consumer from "../channels/consumer"
export default class extends Controller {
static targets = [ "input" ]
connect() {
this.subscription = consumer.subscriptions.create("TypingChannel", {
received: (data) => {
this.renderTyping(data)
}
})
}
renderTyping(data) {
const typing = document.getElementById("typing")
typing.innerHTML = data.message
}
disconnect() {
this.subscription.unsubscribe()
}
}
Is not possible to use turbo stream with action cable. You need to use action cable to get the typing indicator. You can use turbo stream to render the typing indicator.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With