Is it possible to prepend items to an append div in LiveView, when using temporary assigns

I have a basic chat application I’m building to play with liveview. I am using temporary_assigns with the messages like this:

assign(socket, %{
messages: some_messages,
}), temporary_assigns: [messages: []]}

My messages div uses append (this is for newly created messsages) like this:

<div id="chat-messages" phx-update="append" phx-hook="messages">
# render messages here

In my messages hook, I want to listen for a scrollTop of 0 to prepend earlier messages:

Hooks.messages = {
  mounted() {
    var $el = $(this.el)
    var that = this;
    $el.on("scroll", function (ev) {
      if ($el.scrollTop() == 0) {
        that.pushEvent("load_more", {})

In my handle_event for the load_more I have this:

new_msgs = some_func_to_get_messages_before_the_current_messages
{:noreply, update(socket, :messages, fn messages -> new_msgs ++ messages end)}

At this point socket.assigns.messages would be [] because of temporary_assigns. Current this doesn’t do anything, the new messages can’t be seen.

What’s the best way to handle this loading more messages on scroll?

I am not an expert in Live View, but you may want to try to adapt the infinite scroll example from the official docs to your use case:

Hooks.InfiniteScroll = {
  page() { return },
    this.pending =
    window.addEventListener("scroll", e => {
      if(this.pending == && scrollAt() > 90){
        this.pending = + 1
        this.pushEvent("load-more", {})
  updated(){ this.pending = }

That example just covers sending the load-more event, which I can successfully do. My issue is not sending the event to the backend, it’s handling loading more messages on the backend. The JS is not my issue, it’s the Elixir code I need to run after I receive the event.


Did you ever find a solution for this? This is currently a problem I am having with LiveView and have had to resort to javascript to fill.