Add a “X is writing…” with Rails and Turbo

This article was originally published on Rails Designer

Apps that rely heavily on text messaging (like Slack, Whatsapp and Telegram) often implement some kind of indication or status if the other party (in the chat room) is typing.

This kind of UX…


This content originally appeared on DEV Community and was authored by Rails Designer

This article was originally published on Rails Designer

Apps that rely heavily on text messaging (like Slack, Whatsapp and Telegram) often implement some kind of indication or status if the other party (in the chat room) is typing.

This kind of UX might be useful for engagement or set expectations. Based on your app, seeing the other is typing might keep them around longer. Or it might keep them from adding another message, until you got the message the other was typing.

Luckily for us Rails developers, with the release of Hotwire, this is pretty straightforward to add. Let's dive in.

I assume you already have some sort of messaging/chat system in place. If you don't check out the video on hotwired.dev where DHH himself builds a basic chat app.

What is needed?

  1. Tweak the New Message form
  2. Create a Stimulus controller
  3. Create a Rails controller

1. Tweak the New Message form

Add references of the stimulus controller (writing-indicator) to the form element and add an empty div with an id of writing_indicator). This div is where the “X is typing…” text will be inserted.

# app/views/messages/_form.html.erb
<⁠⁠%= form_with(model: message, data: { controller: "writing-indicator", writing_indicator_room_id_value: room.id, writing_indicator_user_id_value: Current.user.id } }) do |form| %>
  <⁠⁠%= form.text_area :content, data: { action: "input->writing-indicator#update" } %>
<⁠⁠% end %>

<div id="writing_indicator">
</div>

2. Create a Stimulus controller

This controller uses two third-party packages @rails/request.js and debounce from lodash.

// app/javascript/controllers/writing_indicator_controller.js
import { Controller } from "@hotwired/stimulus"
import { get } from "@rails/request.js"
import { debounce } from 'lodash"

export default class extends Controller {
  static values = {
    roomId: Number,
    userId: Number,
    debounce: { type: Number, default: 300 }
  }

  initialize() {
    this.update = debounce(this.update.bind(this), this.debounceValue)
  }

  update(event) {
    const url = "/writing_indicator/"

    get(url, {
      query: { user_id: this.userIdValue, room_id: this.roomIdValue },
      responseKind: "turbo-stream"
    })
  }
}

The debounce is to make sure the requests are not fired on every input change in the textarea, but with a slight delay (and reset every time an input falls within the debounceValue number). The update() function is where the magic is happening, by sending a request to the controller's action created below. It adds both the user_id and the room_id that are both needed in the controller.

3. Create a Rails controller

The update action in this controller broadcasts the app/views/writing_indicators/_update.html.erb partial to the room_#{room_id} channel and replaces the writing_indicator div, created earlier.

# app/controllers/writing_indicators_controller.rb
def update
  room_id = params[:room_id]
  user = User.find(params[:user_id])

Turbo::StreamsChannel.broadcast_replace_to "room_#{room_id}",
    target: "writing_indicator",
    partial: "writing_indicators/update",
    locals: { user: user }
end

Also create a turbo_stream response for the above controller action.

# app/views/writing_indicators/_update.html.erb
<p>
  <⁠%= user.name %> is writing…
</p>

This view assumes the user has a name method. Don't forget to add a route for above action (resource :writing_indicator) inconfig/routes.rb. Lastly make sure you use the correct channel to broadcast too (eg.turbo_stream_from @room`), you likely already have something like this in place for the chat functionality.

Next steps

While these steps will add the basics of this kind of UX to your app, there are more things to consider:

  • what should happen on submit?
  • what should happen after typing and then closing the screen?

I'll leave that up to you, but feel free to reach out if you get stuck on anything with the above points.

And that is really all you need to get a “X is writing…” UX in your Rails chat app. Mind-blown already? Of course it needs some UI love, but I leave that up you or you can check out Rails Designer. It's the first professionally-designed UI components library for Rails. Built with ViewComponent, designed with Tailwind CSS and enhanced with Hotwire.


This content originally appeared on DEV Community and was authored by Rails Designer


Print Share Comment Cite Upload Translate Updates
APA

Rails Designer | Sciencx (2024-07-18T08:00:00+00:00) Add a “X is writing…” with Rails and Turbo. Retrieved from https://www.scien.cx/2024/07/18/add-a-x-is-writing-with-rails-and-turbo/

MLA
" » Add a “X is writing…” with Rails and Turbo." Rails Designer | Sciencx - Thursday July 18, 2024, https://www.scien.cx/2024/07/18/add-a-x-is-writing-with-rails-and-turbo/
HARVARD
Rails Designer | Sciencx Thursday July 18, 2024 » Add a “X is writing…” with Rails and Turbo., viewed ,<https://www.scien.cx/2024/07/18/add-a-x-is-writing-with-rails-and-turbo/>
VANCOUVER
Rails Designer | Sciencx - » Add a “X is writing…” with Rails and Turbo. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/07/18/add-a-x-is-writing-with-rails-and-turbo/
CHICAGO
" » Add a “X is writing…” with Rails and Turbo." Rails Designer | Sciencx - Accessed . https://www.scien.cx/2024/07/18/add-a-x-is-writing-with-rails-and-turbo/
IEEE
" » Add a “X is writing…” with Rails and Turbo." Rails Designer | Sciencx [Online]. Available: https://www.scien.cx/2024/07/18/add-a-x-is-writing-with-rails-and-turbo/. [Accessed: ]
rf:citation
» Add a “X is writing…” with Rails and Turbo | Rails Designer | Sciencx | https://www.scien.cx/2024/07/18/add-a-x-is-writing-with-rails-and-turbo/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.