Hotwire Discussion

How to edit target content on turbo:before-stream-render?

Hi,
I’m trying to do a chat application, that when current user is the owner of the message, the massage should show on right, if other use send the massage, it should stay on the left.

I read @dhh saying tht is not possible to send current user on broadcast (Authentication and Devise with broadcasts - #4 by dhh), so I’m trying to add the current user on a parent element of the page in a data attribute and use it on turbo:before-stream-render to add de right class

But I tried to change in so many ways templateElement but don’t found a way that works.

  var updateMessages = function(e) {
    var user_id = $('#notes-container').data('user');
    console.log('a');
    var templateContent = $(e.target.templateElement.content);

    templateContent.find('.message-row').each(function(idx, el) {
      var el_user_id = el.dataset.user;
      console.log(el_user_id);
      el.classList.add(el_user_id == user_id ? 'right-message' : 'left-message')
    });
  }
  $(document).on('turbo:before-stream-render', updateMessages);

There is a way to change the content of templateElement?

Same code without Jquery

I change updateMessages to not use Jquery

  var updateMessages = function(e) {
    var user_id = $('#notes-container').data('user');

    e.target.templateElement.content.querySelectorAll('.message-row').forEach(function(el, idx) {
      var el_user_id = el.dataset.user;
      console.log(el_user_id);
      el.classList.add(el_user_id == user_id ? 'right-message' : 'left-message')
    });
  }

Still not working

If your project is using stimulus js you can do this very easily.
You have the current user’s id on the page, right?. When you broadcast the message, make sure it’s html also has the user id of the sender of the message and is controlled by a stimulus js controller looking something like this:

(In my phone so I’ll write some pseudo code)

export default class extend Controller {
  static values = { senderUserId: String }
  static classes = {…}
  connect(){
    this.currentUser = // get user id from page
    setSenderCss()
  }

  setSenderCss () {
    // if sender == current add one css class
    // else add another one
  }
}

The way stimulus works is by observing when a new element is added to the page. When that happens it runs the connect() lifecycle method. If every single message is controlled by an instance of the messages controller the decision of wether it’s painted to the left or right is made as each element enters the page

Hi,
The fact is that that code works, the frame (from controller) was tricking me.

Sorry.