skip to Main Content

Alright, first question here!
I’m writing a chat application and what i need is for new messages to be displayed immediately, not just after a reload. I don’t know the best way to go about this; maybe reload just the chat-message-container again? Or display new messages as their own chatMessage elements? In either case I wouldn’t know how to do it.
I commented in the JS where I think the required logic needs to be. Any help is much appreciated!!

The HTML and JS:

{% extends "main.html" %} {% block content %}
<main class="messagePage my-xl">
  <div class="content-box">
    <div class="chat-header">
      <a class="backButton" href="{% url 'inbox' %}"><i class="fa-solid fa-arrow-left"></i></a>
      <h1 class="username-top">{{ other_user.username }}</h1>
    </div>

    <div class="chat-message-container">
      {% for chat_message in chat_messages %}
      <div
        class="chatMessage{% if chat_message.sender == profile %} chatMessage--right{% else %} chatMessage--left{% endif %}"
        id="chat-messages">
        <small>{{ chat_message.content|safe }}</small>
      </div>
      {% endfor %}
    </div>

    <div class="chat-bottom-section">
      <form method="post" action="" class="chat-form">
        {% csrf_token %}
        <div class="chat-input">
          <input
            type="text"
            name="content"
            class="flex-1 mr-3"
            placeholder="Your message..."
            id="chat-message-input"
          />
          <button id="chat-message-submit">
            <span class="icon-btn material-symbols-outlined">send</span>
          </button>
        </div>
      </form>
    </div>
  </div>
</main>
{% endblock %} 
{%block script%} 
{{ room.id|json_script:"json-room-id" }} 
{{profile.id|json_script:"json-sender-id" }} 
{{other_user.id|json_script:"json-receiver-id" }}

<script>
  const roomId = JSON.parse(
    document.getElementById("json-room-id").textContent
  );
  const senderId = JSON.parse(
    document.getElementById("json-sender-id").textContent
  );
  const receiverId = JSON.parse(
    document.getElementById("json-receiver-id").textContent
  );
  const chatSocket = new WebSocket(
    "ws://" + window.location.host + "/ws/" + roomId + "/"
  );

  chatSocket.onopen = function (e) {
    console.log("yas bitch");
  };

  chatSocket.onclose = function (e) {
    console.log("onclose");
  };

  chatSocket.onerror = function (e) {
    console.error("WebSocket error:", e);
  };

  chatSocket.onmessage = function (e) {
    try {
      const data = JSON.parse(e.data);
      /*logic to append new messages/reload the css element*/
      scrollToBottom();
    } catch (error) {
      console.error("Error parsing WebSocket data:", error);
    }
  };

  document.querySelector("#chat-message-input").focus();
  document.querySelector("#chat-message-input").onkeyup = function (e) {
    if (e.keyCode === 13) {
      e.preventDefault();
      document.querySelector("#chat-message-submit").click();
    }
  };

  document.querySelector("#chat-message-submit").onclick = function (e) {
    e.preventDefault();

    const messageInputDom = document.querySelector("#chat-message-input");
    const message_content = messageInputDom.value;

    console.log({
      message_content: message_content,
      senderId: senderId,
      receiverId: receiverId,
      roomId: roomId,
    });

    chatSocket.send(
      JSON.stringify({
        message_content: message_content,
        senderId: senderId,
        receiverId: receiverId,
        roomId: roomId,
      })
    );

    messageInputDom.value = "";

    return false;
  };



  function scrollToBottom() {
    let objDiv = document.getElementById("chat-messages");
    objDiv.scrollTop = objDiv.scrollHeight;
  }
  scrollToBottom();

</script>
{%endblock%}

The view:

@login_required(login_url="login")
def private_chat_view(request, pk):
    profile = request.user.profile
    room = Room.objects.get(id=pk)
    other_user_profile = room.get_partner(profile)
    chat_messages = room.messages.all().reverse()
    
    for chat_message in chat_messages:
        chat_message.content = insert_line_breaks(chat_message.content)

    return render(request, 'chats/room.html', {
        'chat_messages': chat_messages,
        'room': room,
        'profile': profile,
        'other_user': other_user_profile
    })

I tried both approaches I previously mentioned, in both cases nothing happened.

2

Answers


  1. Chosen as BEST ANSWER

    The fix was using jquery:

    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    

      chatSocket.onmessage = function (e) {
        try {
          const data = JSON.parse(e.data);
          $( "#chat-message-container" ).load(window.location.href + " #chat-message-container" );
        } catch (error) {
          console.error("Error parsing WebSocket data:", error);
        }
        console.log("scrolling");
        scrollToBottom();
      };


  2. You should use django-socketio package to real-time chatting.

    1. Install django-socketio
      pip install django-socketio
    2. Add django_socketio in your installed_app and django_socketio.url in your URLs
    3. You can use socketio template tags in your templates, ex socket.connect()
    4. run socket server by runserver_socektio host:port

    Then you can subscribe channiel in client, and send/receive messages.
    (socket.send, socket.broadcast ...)

    Socket programming is not difficult, but you should learn step by step and you can solve the issue. Good luck.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search