Part 5 - More Fun with Broadcasts

Removing Chat Messages

Let’s continue to build on this basic chat application by allowing the user to remove messages. Let’s walk through the steps to accomplish this:

  • Add links to the message component template to remove the message. Add a message_id to each list item so Turbo knows which message to delete.

  • Create a view that deletes the message.

  • Add an on_delete method to the ModelBroadcast. Tell the room subscribers to remove the message div by ID.

Start by adding a unique id to each <li> element. Then add a link to remove that message in the template.

templates/chat/components/message.html
<li id="message-{{message.id}}">{{message.created_at}}: {{message.text}} <a href="{% url 'message_delete' message.id %}">[Remove]</a></li>

This new delete link with redirect the entire page. To only send a request to the message_delete url, the links need to be inside a turbo frame. Wrap the <ul> element in room_detail.html inside a turbo frame.

templates/chat/room_detail.html
<turbo-frame id="message-list">
    <ul id="messages">
        {% for message in room.messages.all%}
            {% include "chat/components/message.html"  with message=message only %}
        {% endfor %}
    </ul>
</turbo-frame>

Add the message_delete url and view.

turbotutorial/urls.py
urlpatterns = [
   ...
   path("message/<pk:message_id>/delete", views.message_delete, name="message_delete"),
]
chat/views.py
from django.http import HttpResponse

...

def message_delete(request, message_id):
    message = get_object_or_404(Message, pk=message_id)
    message.delete()
    return HttpResponse()

And finally, let your message broadcast tell clients subscribed to the message’s room to remove any item on the page with the unique id specified in the template.

chat/broadcasts.py
@turbo.register(Message)
class MessageBroadcast(turbo.ModelBroadcast):

    ...

    def on_delete(self, message, *args, **kwargs):
        message.room.turbo.remove(id=f"message-{message.id}")

Note

Notice that .remove() is used without first calling .render(). Remove only takes away content, so rendering a template is not necessary.